decodebin: Add autoplug-query signal to handle queries for yet unconnected elements
[platform/upstream/gstreamer.git] / gst / videoscale / vs_image.c
1 /*
2  * Image Scaling Functions
3  * Copyright (c) 2005-2012 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 <string.h>
32
33 #include "vs_scanline.h"
34 #include "vs_image.h"
35
36 #include "gstvideoscaleorc.h"
37 #include <gst/gst.h>
38
39 #define ROUND_UP_2(x)  (((x)+1)&~1)
40 #define ROUND_UP_4(x)  (((x)+3)&~3)
41 #define ROUND_UP_8(x)  (((x)+7)&~7)
42
43 void
44 vs_image_scale_nearest_RGBA (const VSImage * dest, const VSImage * src,
45     uint8_t * tmpbuf)
46 {
47   int acc;
48   int y_increment;
49   int x_increment;
50   int i;
51   int j;
52   int prev_j;
53
54   if (dest->height == 1)
55     y_increment = 0;
56   else
57     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
58
59   if (dest->width == 1)
60     x_increment = 0;
61   else
62     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
63
64
65   acc = 0;
66   prev_j = -1;
67   for (i = 0; i < dest->height; i++) {
68     j = acc >> 16;
69
70     if (j == prev_j) {
71       memcpy (dest->pixels + i * dest->stride,
72           dest->pixels + (i - 1) * dest->stride, dest->width * 4);
73     } else {
74       video_scale_orc_resample_nearest_u32 (dest->pixels + i * dest->stride,
75           src->pixels + j * src->stride, 0, x_increment, dest->width);
76     }
77
78     prev_j = j;
79     acc += y_increment;
80   }
81 }
82
83 void
84 vs_image_scale_linear_RGBA (const VSImage * dest, const VSImage * src,
85     uint8_t * tmpbuf)
86 {
87   int acc;
88   int y_increment;
89   int x_increment;
90   int y1;
91   int i;
92   int j;
93   int x;
94   int dest_size;
95
96   if (dest->height == 1)
97     y_increment = 0;
98   else
99     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
100
101   if (dest->width == 1)
102     x_increment = 0;
103   else
104     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
105
106   dest_size = dest->width * 4;
107
108 #define LINE(x) ((tmpbuf) + (dest_size)*((x)&1))
109
110   acc = 0;
111   video_scale_orc_resample_bilinear_u32 (LINE (0), src->pixels,
112       0, x_increment, dest->width);
113   y1 = 0;
114   for (i = 0; i < dest->height; i++) {
115     j = acc >> 16;
116     x = acc & 0xffff;
117
118     if (x == 0) {
119       memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size);
120     } else {
121       if (j > y1) {
122         video_scale_orc_resample_bilinear_u32 (LINE (j),
123             src->pixels + j * src->stride, 0, x_increment, dest->width);
124         y1++;
125       }
126       if (j >= y1) {
127         video_scale_orc_resample_bilinear_u32 (LINE (j + 1),
128             src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
129         y1++;
130       }
131       video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
132           LINE (j), LINE (j + 1), (x >> 8), dest->width * 4);
133     }
134
135     acc += y_increment;
136   }
137 }
138
139
140 void
141 vs_image_scale_nearest_RGB (const VSImage * dest, const VSImage * src,
142     uint8_t * tmpbuf)
143 {
144   int acc;
145   int y_increment;
146   int x_increment;
147   int i;
148   int j;
149   int xacc;
150
151   if (dest->height == 1)
152     y_increment = 0;
153   else
154     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
155
156   if (dest->width == 1)
157     x_increment = 0;
158   else
159     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
160
161   acc = 0;
162   for (i = 0; i < dest->height; i++) {
163     j = acc >> 16;
164
165     xacc = 0;
166     vs_scanline_resample_nearest_RGB (dest->pixels + i * dest->stride,
167         src->pixels + j * src->stride, src->width, dest->width, &xacc,
168         x_increment);
169
170     acc += y_increment;
171   }
172 }
173
174 void
175 vs_image_scale_linear_RGB (const VSImage * dest, const VSImage * src,
176     uint8_t * tmpbuf)
177 {
178   int acc;
179   int y_increment;
180   int x_increment;
181   uint8_t *tmp1;
182   uint8_t *tmp2;
183   int y1;
184   int y2;
185   int i;
186   int j;
187   int x;
188   int dest_size;
189   int xacc;
190
191   if (dest->height == 1)
192     y_increment = 0;
193   else
194     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
195
196   if (dest->width == 1)
197     x_increment = 0;
198   else
199     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
200
201   dest_size = dest->width * 3;
202
203   tmp1 = tmpbuf;
204   tmp2 = tmpbuf + dest_size;
205
206   acc = 0;
207   xacc = 0;
208   y2 = -1;
209   vs_scanline_resample_linear_RGB (tmp1, src->pixels, src->width, dest->width,
210       &xacc, x_increment);
211   y1 = 0;
212   for (i = 0; i < dest->height; i++) {
213     j = acc >> 16;
214     x = acc & 0xffff;
215
216     if (x == 0) {
217       if (j == y1) {
218         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
219       } else if (j == y2) {
220         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
221       } else {
222         xacc = 0;
223         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
224             src->width, dest->width, &xacc, x_increment);
225         y1 = j;
226         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
227       }
228     } else {
229       if (j == y1) {
230         if (j + 1 != y2) {
231           xacc = 0;
232           vs_scanline_resample_linear_RGB (tmp2,
233               src->pixels + (j + 1) * src->stride, src->width, dest->width,
234               &xacc, x_increment);
235           y2 = j + 1;
236         }
237         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
238             tmp1, tmp2, dest->width, x);
239       } else if (j == y2) {
240         if (j + 1 != y1) {
241           xacc = 0;
242           vs_scanline_resample_linear_RGB (tmp1,
243               src->pixels + (j + 1) * src->stride, src->width, dest->width,
244               &xacc, x_increment);
245           y1 = j + 1;
246         }
247         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
248             tmp2, tmp1, dest->width, x);
249       } else {
250         xacc = 0;
251         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
252             src->width, dest->width, &xacc, x_increment);
253         y1 = j;
254         xacc = 0;
255         vs_scanline_resample_linear_RGB (tmp2,
256             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
257             x_increment);
258         y2 = (j + 1);
259         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
260             tmp1, tmp2, dest->width, x);
261       }
262     }
263
264     acc += y_increment;
265   }
266 }
267
268 /* YUYV */
269
270 void
271 vs_image_scale_nearest_YUYV (const VSImage * dest, const VSImage * src,
272     uint8_t * tmpbuf)
273 {
274   int acc;
275   int y_increment;
276   int x_increment;
277   int i;
278   int j;
279   int xacc;
280
281   if (dest->height == 1)
282     y_increment = 0;
283   else
284     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
285
286   if (dest->width == 1)
287     x_increment = 0;
288   else
289     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
290
291   acc = 0;
292   for (i = 0; i < dest->height; i++) {
293     j = acc >> 16;
294
295     xacc = 0;
296     vs_scanline_resample_nearest_YUYV (dest->pixels + i * dest->stride,
297         src->pixels + j * src->stride, src->width, dest->width, &xacc,
298         x_increment);
299
300     acc += y_increment;
301   }
302 }
303
304 void
305 vs_image_scale_linear_YUYV (const VSImage * dest, const VSImage * src,
306     uint8_t * tmpbuf)
307 {
308   int acc;
309   int y_increment;
310   int x_increment;
311   uint8_t *tmp1;
312   uint8_t *tmp2;
313   int y1;
314   int y2;
315   int i;
316   int j;
317   int x;
318   int dest_size;
319   int xacc;
320
321   if (dest->height == 1)
322     y_increment = 0;
323   else
324     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
325
326   if (dest->width == 1)
327     x_increment = 0;
328   else
329     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
330
331   dest_size = ROUND_UP_4 (dest->width * 2);
332
333   tmp1 = tmpbuf;
334   tmp2 = tmpbuf + dest_size;
335
336   acc = 0;
337   xacc = 0;
338   y2 = -1;
339   vs_scanline_resample_linear_YUYV (tmp1, src->pixels, src->width, dest->width,
340       &xacc, x_increment);
341   y1 = 0;
342   for (i = 0; i < dest->height; i++) {
343     j = acc >> 16;
344     x = acc & 0xffff;
345
346     if (x == 0) {
347       if (j == y1) {
348         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
349       } else if (j == y2) {
350         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
351       } else {
352         xacc = 0;
353         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
354             src->width, dest->width, &xacc, x_increment);
355         y1 = j;
356         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
357       }
358     } else {
359       if (j == y1) {
360         if (j + 1 != y2) {
361           xacc = 0;
362           vs_scanline_resample_linear_YUYV (tmp2,
363               src->pixels + (j + 1) * src->stride, src->width, dest->width,
364               &xacc, x_increment);
365           y2 = j + 1;
366         }
367         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
368             tmp1, tmp2, dest->width, x);
369       } else if (j == y2) {
370         if (j + 1 != y1) {
371           xacc = 0;
372           vs_scanline_resample_linear_YUYV (tmp1,
373               src->pixels + (j + 1) * src->stride, src->width, dest->width,
374               &xacc, x_increment);
375           y1 = j + 1;
376         }
377         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
378             tmp2, tmp1, dest->width, x);
379       } else {
380         xacc = 0;
381         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
382             src->width, dest->width, &xacc, x_increment);
383         y1 = j;
384         xacc = 0;
385         vs_scanline_resample_linear_YUYV (tmp2,
386             src->pixels + (j + 1) * src->stride, src->width, dest->width,
387             &xacc, x_increment);
388         y2 = (j + 1);
389         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
390             tmp1, tmp2, dest->width, x);
391       }
392     }
393
394     acc += y_increment;
395   }
396 }
397
398 /* UYVY */
399
400 void
401 vs_image_scale_nearest_UYVY (const VSImage * dest, const VSImage * src,
402     uint8_t * tmpbuf)
403 {
404   int acc;
405   int y_increment;
406   int x_increment;
407   int i;
408   int j;
409   int xacc;
410
411   if (dest->height == 1)
412     y_increment = 0;
413   else
414     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
415
416   if (dest->width == 1)
417     x_increment = 0;
418   else
419     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
420
421   acc = 0;
422   for (i = 0; i < dest->height; i++) {
423     j = acc >> 16;
424
425     xacc = 0;
426     vs_scanline_resample_nearest_UYVY (dest->pixels + i * dest->stride,
427         src->pixels + j * src->stride, src->width, dest->width, &xacc,
428         x_increment);
429
430     acc += y_increment;
431   }
432 }
433
434 void
435 vs_image_scale_linear_UYVY (const VSImage * dest, const VSImage * src,
436     uint8_t * tmpbuf)
437 {
438   int acc;
439   int y_increment;
440   int x_increment;
441   uint8_t *tmp1;
442   uint8_t *tmp2;
443   int y1;
444   int y2;
445   int i;
446   int j;
447   int x;
448   int dest_size;
449   int xacc;
450
451   if (dest->height == 1)
452     y_increment = 0;
453   else
454     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
455
456   if (dest->width == 1)
457     x_increment = 0;
458   else
459     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
460
461   dest_size = ROUND_UP_4 (dest->width * 2);
462
463   tmp1 = tmpbuf;
464   tmp2 = tmpbuf + dest_size;
465
466   acc = 0;
467   xacc = 0;
468   y2 = -1;
469   vs_scanline_resample_linear_UYVY (tmp1, src->pixels, src->width, dest->width,
470       &xacc, x_increment);
471   y1 = 0;
472   for (i = 0; i < dest->height; i++) {
473     j = acc >> 16;
474     x = acc & 0xffff;
475
476     if (x == 0) {
477       if (j == y1) {
478         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
479       } else if (j == y2) {
480         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
481       } else {
482         xacc = 0;
483         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
484             src->width, dest->width, &xacc, x_increment);
485         y1 = j;
486         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
487       }
488     } else {
489       if (j == y1) {
490         if (j + 1 != y2) {
491           xacc = 0;
492           vs_scanline_resample_linear_UYVY (tmp2,
493               src->pixels + (j + 1) * src->stride, src->width, dest->width,
494               &xacc, x_increment);
495           y2 = j + 1;
496         }
497         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
498             tmp1, tmp2, dest->width, x);
499       } else if (j == y2) {
500         if (j + 1 != y1) {
501           xacc = 0;
502           vs_scanline_resample_linear_UYVY (tmp1,
503               src->pixels + (j + 1) * src->stride, src->width, dest->width,
504               &xacc, x_increment);
505           y1 = j + 1;
506         }
507         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
508             tmp2, tmp1, dest->width, x);
509       } else {
510         xacc = 0;
511         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
512             src->width, dest->width, &xacc, x_increment);
513         y1 = j;
514         xacc = 0;
515         vs_scanline_resample_linear_UYVY (tmp2,
516             src->pixels + (j + 1) * src->stride, src->width, dest->width,
517             &xacc, x_increment);
518         y2 = (j + 1);
519         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
520             tmp1, tmp2, dest->width, x);
521       }
522     }
523
524     acc += y_increment;
525   }
526 }
527
528 /* NV12 */
529
530 void
531 vs_image_scale_nearest_NV12 (const VSImage * dest, const VSImage * src,
532     uint8_t * tmpbuf)
533 {
534   int acc;
535   int y_increment;
536   int x_increment;
537   int i;
538   int j;
539   int xacc;
540
541   if (dest->height == 1)
542     y_increment = 0;
543   else
544     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
545
546   if (dest->width == 1)
547     x_increment = 0;
548   else
549     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
550
551   acc = 0;
552   for (i = 0; i < dest->height; i++) {
553     j = acc >> 16;
554
555     xacc = 0;
556     vs_scanline_resample_nearest_NV12 (dest->pixels + i * dest->stride,
557         src->pixels + j * src->stride, src->width, dest->width, &xacc,
558         x_increment);
559
560     acc += y_increment;
561   }
562 }
563
564 void
565 vs_image_scale_linear_NV12 (const VSImage * dest, const VSImage * src,
566     uint8_t * tmpbuf)
567 {
568   int acc;
569   int y_increment;
570   int x_increment;
571   uint8_t *tmp1;
572   uint8_t *tmp2;
573   int y1;
574   int y2;
575   int i;
576   int j;
577   int x;
578   int dest_size;
579   int xacc;
580
581   if (dest->height == 1)
582     y_increment = 0;
583   else
584     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
585
586   if (dest->width == 1)
587     x_increment = 0;
588   else
589     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
590
591   dest_size = ROUND_UP_4 (dest->width * 2);
592
593   tmp1 = tmpbuf;
594   tmp2 = tmpbuf + dest_size;
595
596   acc = 0;
597   xacc = 0;
598   y2 = -1;
599   vs_scanline_resample_linear_NV12 (tmp1, src->pixels, src->width, dest->width,
600       &xacc, x_increment);
601   y1 = 0;
602   for (i = 0; i < dest->height; i++) {
603     j = acc >> 16;
604     x = acc & 0xffff;
605
606     if (x == 0) {
607       if (j == y1) {
608         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
609       } else if (j == y2) {
610         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
611       } else {
612         xacc = 0;
613         vs_scanline_resample_linear_NV12 (tmp1, src->pixels + j * src->stride,
614             src->width, dest->width, &xacc, x_increment);
615         y1 = j;
616         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
617       }
618     } else {
619       if (j == y1) {
620         if (j + 1 != y2) {
621           xacc = 0;
622           vs_scanline_resample_linear_NV12 (tmp2,
623               src->pixels + (j + 1) * src->stride, src->width, dest->width,
624               &xacc, x_increment);
625           y2 = j + 1;
626         }
627         vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
628             tmp1, tmp2, dest->width, x);
629       } else if (j == y2) {
630         if (j + 1 != y1) {
631           xacc = 0;
632           vs_scanline_resample_linear_NV12 (tmp1,
633               src->pixels + (j + 1) * src->stride, src->width, dest->width,
634               &xacc, x_increment);
635           y1 = j + 1;
636         }
637         vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
638             tmp2, tmp1, dest->width, x);
639       } else {
640         xacc = 0;
641         vs_scanline_resample_linear_NV12 (tmp1, src->pixels + j * src->stride,
642             src->width, dest->width, &xacc, x_increment);
643         y1 = j;
644         xacc = 0;
645         vs_scanline_resample_linear_NV12 (tmp2,
646             src->pixels + (j + 1) * src->stride, src->width, dest->width,
647             &xacc, x_increment);
648         y2 = (j + 1);
649         vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
650             tmp1, tmp2, dest->width, x);
651       }
652     }
653
654     acc += y_increment;
655   }
656 }
657
658 /* greyscale */
659
660 void
661 vs_image_scale_nearest_Y (const VSImage * dest, const VSImage * src,
662     uint8_t * tmpbuf)
663 {
664   int acc;
665   int y_increment;
666   int x_increment;
667   int i;
668   int j;
669
670   if (dest->height == 1)
671     y_increment = 0;
672   else
673     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
674
675   if (dest->width == 1)
676     x_increment = 0;
677   else
678     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
679
680   acc = 0;
681   for (i = 0; i < dest->height; i++) {
682     j = acc >> 16;
683
684     video_scale_orc_resample_nearest_u8 (dest->pixels + i * dest->stride,
685         src->pixels + j * src->stride, 0, x_increment, dest->width);
686     acc += y_increment;
687   }
688 }
689
690 void
691 vs_image_scale_linear_Y (const VSImage * dest, const VSImage * src,
692     uint8_t * tmpbuf)
693 {
694   int acc;
695   int y_increment;
696   int x_increment;
697   uint8_t *tmp1;
698   uint8_t *tmp2;
699   int y1;
700   int y2;
701   int i;
702   int j;
703   int x;
704   int dest_size;
705
706   if (dest->height == 1)
707     y_increment = 0;
708   else
709     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
710
711   if (dest->width == 1)
712     x_increment = 0;
713   else
714     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
715
716   dest_size = dest->width;
717
718   tmp1 = tmpbuf;
719   tmp2 = tmpbuf + dest_size;
720
721   acc = 0;
722   y2 = -1;
723   video_scale_orc_resample_bilinear_u8 (tmp1, src->pixels,
724       0, x_increment, dest->width);
725   y1 = 0;
726   for (i = 0; i < dest->height; i++) {
727     j = acc >> 16;
728     x = acc & 0xffff;
729
730     if (x == 0) {
731       if (j == y1) {
732         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
733       } else if (j == y2) {
734         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
735       } else {
736         video_scale_orc_resample_bilinear_u8 (tmp1,
737             src->pixels + j * src->stride, 0, x_increment, dest->width);
738         y1 = j;
739         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
740       }
741     } else {
742       if (j == y1) {
743         if (j + 1 != y2) {
744           video_scale_orc_resample_bilinear_u8 (tmp2,
745               src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
746           y2 = j + 1;
747         }
748         if ((x >> 8) == 0) {
749           memcpy (dest->pixels + i * dest->stride, tmp1, dest->width);
750         } else {
751           video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
752               tmp1, tmp2, (x >> 8), dest->width);
753         }
754       } else if (j == y2) {
755         if (j + 1 != y1) {
756           video_scale_orc_resample_bilinear_u8 (tmp1,
757               src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
758           y1 = j + 1;
759         }
760         if ((x >> 8) == 0) {
761           memcpy (dest->pixels + i * dest->stride, tmp2, dest->width);
762         } else {
763           video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
764               tmp2, tmp1, (x >> 8), dest->width);
765         }
766       } else {
767         video_scale_orc_resample_bilinear_u8 (tmp1,
768             src->pixels + j * src->stride, 0, x_increment, dest->width);
769         y1 = j;
770         video_scale_orc_resample_bilinear_u8 (tmp2,
771             src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
772         y2 = (j + 1);
773         if ((x >> 8) == 0) {
774           memcpy (dest->pixels + i * dest->stride, tmp1, dest->width);
775         } else {
776           video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
777               tmp1, tmp2, (x >> 8), dest->width);
778         }
779       }
780     }
781
782     acc += y_increment;
783   }
784 }
785
786 void
787 vs_image_scale_nearest_Y16 (const VSImage * dest, const VSImage * src,
788     uint8_t * tmpbuf)
789 {
790   int acc;
791   int y_increment;
792   int x_increment;
793   int i;
794   int j;
795   int xacc;
796
797   if (dest->height == 1)
798     y_increment = 0;
799   else
800     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
801
802   if (dest->width == 1)
803     x_increment = 0;
804   else
805     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
806
807   acc = 0;
808   for (i = 0; i < dest->height; i++) {
809     j = acc >> 16;
810
811     xacc = 0;
812     vs_scanline_resample_nearest_Y16 (dest->pixels + i * dest->stride,
813         src->pixels + j * src->stride, src->width, dest->width, &xacc,
814         x_increment);
815
816     acc += y_increment;
817   }
818 }
819
820 void
821 vs_image_scale_linear_Y16 (const VSImage * dest, const VSImage * src,
822     uint8_t * tmpbuf)
823 {
824   int acc;
825   int y_increment;
826   int x_increment;
827   uint8_t *tmp1;
828   uint8_t *tmp2;
829   int y1;
830   int y2;
831   int i;
832   int j;
833   int x;
834   int dest_size;
835   int xacc;
836
837   if (dest->height == 1)
838     y_increment = 0;
839   else
840     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
841
842   if (dest->width == 1)
843     x_increment = 0;
844   else
845     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
846
847   dest_size = 2 * dest->width;
848
849   tmp1 = tmpbuf;
850   tmp2 = tmpbuf + dest_size;
851
852   acc = 0;
853   xacc = 0;
854   y2 = -1;
855   vs_scanline_resample_linear_Y16 (tmp1, src->pixels, src->width, dest->width,
856       &xacc, x_increment);
857   y1 = 0;
858   for (i = 0; i < dest->height; i++) {
859     j = acc >> 16;
860     x = acc & 0xffff;
861
862     if (x == 0) {
863       if (j == y1) {
864         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
865       } else if (j == y2) {
866         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
867       } else {
868         xacc = 0;
869         vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
870             src->width, dest->width, &xacc, x_increment);
871         y1 = j;
872         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
873       }
874     } else {
875       if (j == y1) {
876         if (j + 1 != y2) {
877           xacc = 0;
878           vs_scanline_resample_linear_Y16 (tmp2,
879               src->pixels + (j + 1) * src->stride, src->width, dest->width,
880               &xacc, x_increment);
881           y2 = j + 1;
882         }
883         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
884             tmp1, tmp2, dest->width, x);
885       } else if (j == y2) {
886         if (j + 1 != y1) {
887           xacc = 0;
888           vs_scanline_resample_linear_Y16 (tmp1,
889               src->pixels + (j + 1) * src->stride, src->width, dest->width,
890               &xacc, x_increment);
891           y1 = j + 1;
892         }
893         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
894             tmp2, tmp1, dest->width, x);
895       } else {
896         xacc = 0;
897         vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
898             src->width, dest->width, &xacc, x_increment);
899         y1 = j;
900         xacc = 0;
901         vs_scanline_resample_linear_Y16 (tmp2,
902             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
903             x_increment);
904         y2 = (j + 1);
905         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
906             tmp1, tmp2, dest->width, x);
907       }
908     }
909
910     acc += y_increment;
911   }
912 }
913
914 /* RGB565 */
915
916 void
917 vs_image_scale_nearest_RGB565 (const VSImage * dest, const VSImage * src,
918     uint8_t * tmpbuf)
919 {
920   int acc;
921   int y_increment;
922   int x_increment;
923   int i;
924   int j;
925   int xacc;
926
927   if (dest->height == 1)
928     y_increment = 0;
929   else
930     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
931
932   if (dest->width == 1)
933     x_increment = 0;
934   else
935     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
936
937   acc = 0;
938   for (i = 0; i < dest->height; i++) {
939     j = acc >> 16;
940
941     xacc = 0;
942     vs_scanline_resample_nearest_RGB565 (dest->pixels + i * dest->stride,
943         src->pixels + j * src->stride, src->width, dest->width, &xacc,
944         x_increment);
945
946     acc += y_increment;
947   }
948 }
949
950 void
951 vs_image_scale_linear_RGB565 (const VSImage * dest, const VSImage * src,
952     uint8_t * tmpbuf)
953 {
954   int acc;
955   int y_increment;
956   int x_increment;
957   uint8_t *tmp1;
958   uint8_t *tmp2;
959   int y1;
960   int y2;
961   int i;
962   int j;
963   int x;
964   int dest_size;
965   int xacc;
966
967   if (dest->height == 1)
968     y_increment = 0;
969   else
970     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
971
972   if (dest->width == 1)
973     x_increment = 0;
974   else
975     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
976
977   dest_size = dest->width * 2;
978
979   tmp1 = tmpbuf;
980   tmp2 = tmpbuf + dest_size;
981
982   acc = 0;
983   xacc = 0;
984   y2 = -1;
985   vs_scanline_resample_linear_RGB565 (tmp1, src->pixels, src->width,
986       dest->width, &xacc, x_increment);
987   y1 = 0;
988   for (i = 0; i < dest->height; i++) {
989     j = acc >> 16;
990     x = acc & 0xffff;
991
992     if (x == 0) {
993       if (j == y1) {
994         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
995       } else if (j == y2) {
996         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
997       } else {
998         xacc = 0;
999         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
1000             src->width, dest->width, &xacc, x_increment);
1001         y1 = j;
1002         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1003       }
1004     } else {
1005       if (j == y1) {
1006         if (j + 1 != y2) {
1007           xacc = 0;
1008           vs_scanline_resample_linear_RGB565 (tmp2,
1009               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1010               &xacc, x_increment);
1011           y2 = j + 1;
1012         }
1013         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
1014             tmp1, tmp2, dest->width, x);
1015       } else if (j == y2) {
1016         if (j + 1 != y1) {
1017           xacc = 0;
1018           vs_scanline_resample_linear_RGB565 (tmp1,
1019               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1020               &xacc, x_increment);
1021           y1 = j + 1;
1022         }
1023         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
1024             tmp2, tmp1, dest->width, x);
1025       } else {
1026         xacc = 0;
1027         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
1028             src->width, dest->width, &xacc, x_increment);
1029         y1 = j;
1030         xacc = 0;
1031         vs_scanline_resample_linear_RGB565 (tmp2,
1032             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1033             x_increment);
1034         y2 = (j + 1);
1035         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
1036             tmp1, tmp2, dest->width, x);
1037       }
1038     }
1039
1040     acc += y_increment;
1041   }
1042 }
1043
1044 /* RGB555 */
1045
1046 void
1047 vs_image_scale_nearest_RGB555 (const VSImage * dest, const VSImage * src,
1048     uint8_t * tmpbuf)
1049 {
1050   int acc;
1051   int y_increment;
1052   int x_increment;
1053   int i;
1054   int j;
1055   int xacc;
1056
1057   if (dest->height == 1)
1058     y_increment = 0;
1059   else
1060     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1061
1062   if (dest->width == 1)
1063     x_increment = 0;
1064   else
1065     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1066
1067   acc = 0;
1068   for (i = 0; i < dest->height; i++) {
1069     j = acc >> 16;
1070
1071     xacc = 0;
1072     vs_scanline_resample_nearest_RGB555 (dest->pixels + i * dest->stride,
1073         src->pixels + j * src->stride, src->width, dest->width, &xacc,
1074         x_increment);
1075
1076     acc += y_increment;
1077   }
1078 }
1079
1080 void
1081 vs_image_scale_linear_RGB555 (const VSImage * dest, const VSImage * src,
1082     uint8_t * tmpbuf)
1083 {
1084   int acc;
1085   int y_increment;
1086   int x_increment;
1087   uint8_t *tmp1;
1088   uint8_t *tmp2;
1089   int y1;
1090   int y2;
1091   int i;
1092   int j;
1093   int x;
1094   int dest_size;
1095   int xacc;
1096
1097   if (dest->height == 1)
1098     y_increment = 0;
1099   else
1100     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
1101
1102   if (dest->width == 1)
1103     x_increment = 0;
1104   else
1105     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
1106
1107   dest_size = dest->width * 2;
1108
1109   tmp1 = tmpbuf;
1110   tmp2 = tmpbuf + dest_size;
1111
1112   acc = 0;
1113   xacc = 0;
1114   y2 = -1;
1115   vs_scanline_resample_linear_RGB555 (tmp1, src->pixels, src->width,
1116       dest->width, &xacc, x_increment);
1117   y1 = 0;
1118   for (i = 0; i < dest->height; i++) {
1119     j = acc >> 16;
1120     x = acc & 0xffff;
1121
1122     if (x == 0) {
1123       if (j == y1) {
1124         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1125       } else if (j == y2) {
1126         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
1127       } else {
1128         xacc = 0;
1129         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
1130             src->width, dest->width, &xacc, x_increment);
1131         y1 = j;
1132         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1133       }
1134     } else {
1135       if (j == y1) {
1136         if (j + 1 != y2) {
1137           xacc = 0;
1138           vs_scanline_resample_linear_RGB555 (tmp2,
1139               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1140               &xacc, x_increment);
1141           y2 = j + 1;
1142         }
1143         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1144             tmp1, tmp2, dest->width, x);
1145       } else if (j == y2) {
1146         if (j + 1 != y1) {
1147           xacc = 0;
1148           vs_scanline_resample_linear_RGB555 (tmp1,
1149               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1150               &xacc, x_increment);
1151           y1 = j + 1;
1152         }
1153         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1154             tmp2, tmp1, dest->width, x);
1155       } else {
1156         xacc = 0;
1157         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
1158             src->width, dest->width, &xacc, x_increment);
1159         y1 = j;
1160         xacc = 0;
1161         vs_scanline_resample_linear_RGB555 (tmp2,
1162             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1163             x_increment);
1164         y2 = (j + 1);
1165         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1166             tmp1, tmp2, dest->width, x);
1167       }
1168     }
1169
1170     acc += y_increment;
1171   }
1172 }
1173
1174 void
1175 vs_image_scale_nearest_AYUV64 (const VSImage * dest, const VSImage * src,
1176     uint8_t * tmpbuf8)
1177 {
1178   int acc;
1179   int y_increment;
1180   int x_increment;
1181   int i;
1182   int j;
1183   int prev_j;
1184
1185   if (dest->height == 1)
1186     y_increment = 0;
1187   else
1188     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1189
1190   if (dest->width == 1)
1191     x_increment = 0;
1192   else
1193     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1194
1195
1196   acc = 0;
1197   prev_j = -1;
1198   for (i = 0; i < dest->height; i++) {
1199     j = acc >> 16;
1200
1201     if (j == prev_j) {
1202       memcpy (dest->pixels + i * dest->stride,
1203           dest->pixels + (i - 1) * dest->stride, dest->width * 8);
1204     } else {
1205       int xacc = 0;
1206       vs_scanline_resample_nearest_AYUV64 (dest->pixels + i * dest->stride,
1207           src->pixels + j * src->stride, src->width, dest->width, &xacc,
1208           x_increment);
1209     }
1210
1211     prev_j = j;
1212     acc += y_increment;
1213   }
1214 }
1215
1216 void
1217 vs_image_scale_linear_AYUV64 (const VSImage * dest, const VSImage * src,
1218     uint8_t * tmpbuf)
1219 {
1220   int acc;
1221   int y_increment;
1222   int x_increment;
1223   int y1;
1224   int i;
1225   int j;
1226   int x;
1227   int dest_size;
1228   int xacc;
1229
1230   if (dest->height == 1)
1231     y_increment = 0;
1232   else
1233     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
1234
1235   if (dest->width == 1)
1236     x_increment = 0;
1237   else
1238     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
1239
1240   dest_size = dest->width * 8;
1241
1242 #undef LINE
1243 #define LINE(x) ((guint16 *)((tmpbuf) + (dest_size)*((x)&1)))
1244
1245   acc = 0;
1246   xacc = 0;
1247   vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (0),
1248       src->pixels, src->width, dest->width, &xacc, x_increment);
1249   y1 = 0;
1250   for (i = 0; i < dest->height; i++) {
1251     j = acc >> 16;
1252     x = acc & 0xffff;
1253
1254     if (x == 0) {
1255       memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size);
1256     } else {
1257       if (j > y1) {
1258         xacc = 0;
1259         vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j),
1260             src->pixels + j * src->stride, src->width, dest->width, &xacc,
1261             x_increment);
1262         y1++;
1263       }
1264       if (j >= y1) {
1265         xacc = 0;
1266         vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j + 1),
1267             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1268             x_increment);
1269         video_scale_orc_merge_linear_u16 ((guint16 *) (dest->pixels +
1270                 i * dest->stride), LINE (j), LINE (j + 1), 65536 - x, x,
1271             dest->width * 4);
1272         y1++;
1273       } else {
1274         video_scale_orc_merge_linear_u16 ((guint16 *) (dest->pixels +
1275                 i * dest->stride), LINE (j), LINE (j + 1), 65536 - x, x,
1276             dest->width * 4);
1277       }
1278     }
1279
1280     acc += y_increment;
1281   }
1282 }