2a12d23b76630c9fb0eaba7df746dbb0756091fc
[platform/upstream/gstreamer.git] / gst / videoscale / vs_fill_borders.c
1 /*
2  * Image Scaling Functions
3  * Copyright (c) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
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 <gst/gst.h>
32 #include <string.h>
33
34 #include "vs_fill_borders.h"
35 #include "gstvideoscaleorc.h"
36
37 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
38 #define READ_UINT32(ptr) GST_READ_UINT32_LE(ptr)
39 #define READ_UINT16(ptr) GST_READ_UINT16_LE(ptr)
40 #else
41 #define READ_UINT32(ptr) GST_READ_UINT32_BE(ptr)
42 #define READ_UINT16(ptr) GST_READ_UINT16_BE(ptr)
43 #endif
44
45 void
46 vs_fill_borders_RGBA (const VSImage * dest, const uint8_t * val)
47 {
48   int i;
49   int top = dest->border_top, bottom = dest->border_bottom;
50   int left = dest->border_left, right = dest->border_right;
51   int width = dest->width;
52   int height = dest->height;
53   int real_width = dest->real_width;
54   int stride = dest->stride;
55   int tmp, tmp2;
56   uint8_t *data;
57   uint32_t v = READ_UINT32 (val);
58
59   data = dest->real_pixels;
60   for (i = 0; i < top; i++) {
61     video_scale_orc_splat_u32 ((uint32_t *) data, v, real_width);
62     data += stride;
63   }
64
65   if (left || right) {
66     tmp = height;
67     tmp2 = (left + width) * 4;
68     for (i = 0; i < tmp; i++) {
69       video_scale_orc_splat_u32 ((uint32_t *) data, v, left);
70       video_scale_orc_splat_u32 ((uint32_t *) (data + tmp2), v, right);
71       data += stride;
72     }
73   } else {
74     data += stride * height;
75   }
76
77   for (i = 0; i < bottom; i++) {
78     video_scale_orc_splat_u32 ((uint32_t *) data, v, real_width);
79     data += stride;
80   }
81 }
82
83 static void
84 _memset_u24 (uint8_t * data, uint8_t val1, uint8_t val2, uint8_t val3,
85     unsigned int n)
86 {
87   unsigned int i;
88
89   for (i = 0; i < n; i++) {
90     data[0] = val1;
91     data[1] = val2;
92     data[2] = val3;
93     data += 3;
94   }
95 }
96
97 void
98 vs_fill_borders_RGB (const VSImage * dest, const uint8_t * val)
99 {
100   int i;
101   int top = dest->border_top, bottom = dest->border_bottom;
102   int left = dest->border_left, right = dest->border_right;
103   int width = dest->width;
104   int height = dest->height;
105   int real_width = dest->real_width;
106   int stride = dest->stride;
107   int tmp, tmp2;
108   uint8_t *data;
109
110   data = dest->real_pixels;
111   for (i = 0; i < top; i++) {
112     _memset_u24 (data, val[0], val[1], val[2], real_width);
113     data += stride;
114   }
115
116   if (left || right) {
117     tmp = height;
118     tmp2 = (left + width) * 3;
119     for (i = 0; i < tmp; i++) {
120       _memset_u24 (data, val[0], val[1], val[2], left);
121       _memset_u24 (data + tmp2, val[0], val[1], val[2], right);
122       data += stride;
123     }
124   } else {
125     data += stride * height;
126   }
127
128   for (i = 0; i < bottom; i++) {
129     _memset_u24 (data, val[0], val[1], val[2], real_width);
130     data += stride;
131   }
132 }
133
134 void
135 vs_fill_borders_YUYV (const VSImage * dest, const uint8_t * val)
136 {
137   int i, j;
138   int top = dest->border_top, bottom = dest->border_bottom;
139   int left = dest->border_left, right = dest->border_right;
140   int width = dest->width;
141   int height = dest->height;
142   int real_width = dest->real_width;
143   int stride = dest->stride;
144   int tmp, tmp2;
145   uint8_t *data;
146
147   data = dest->real_pixels;
148   for (i = 0; i < top; i++) {
149     for (j = 0; j < real_width; j++) {
150       data[2 * j] = val[0];
151       data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
152     }
153     data += stride;
154   }
155
156   if (left || right) {
157     tmp = height;
158     tmp2 = (left + width) * 2;
159     for (i = 0; i < tmp; i++) {
160       for (j = 0; j < left; j++) {
161         data[2 * j] = val[0];
162         data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
163       }
164       for (j = 0; j < right; j++) {
165         data[tmp2 + 2 * j] = val[0];
166         data[tmp2 + 2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
167       }
168       data += stride;
169     }
170   } else {
171     data += stride * height;
172   }
173
174   for (i = 0; i < bottom; i++) {
175     for (j = 0; j < real_width; j++) {
176       data[2 * j] = val[0];
177       data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
178     }
179     data += stride;
180   }
181 }
182
183 void
184 vs_fill_borders_UYVY (const VSImage * dest, const uint8_t * val)
185 {
186   int i, j;
187   int top = dest->border_top, bottom = dest->border_bottom;
188   int left = dest->border_left, right = dest->border_right;
189   int width = dest->width;
190   int height = dest->height;
191   int real_width = dest->real_width;
192   int stride = dest->stride;
193   int tmp, tmp2;
194   uint8_t *data;
195
196   data = dest->real_pixels;
197   for (i = 0; i < top; i++) {
198     for (j = 0; j < real_width; j++) {
199       data[2 * j] = (j % 2 == 0) ? val[0] : val[2];
200       data[2 * j + 1] = val[1];
201     }
202     data += stride;
203   }
204
205   if (left || right) {
206     tmp = height;
207     tmp2 = (left + width) * 2;
208     for (i = 0; i < tmp; i++) {
209       for (j = 0; j < left; j++) {
210         data[2 * j] = (j % 2 == 0) ? val[0] : val[2];
211         data[2 * j + 1] = val[1];
212       }
213       for (j = 0; j < right; j++) {
214         data[tmp2 + 2 * j] = (j % 2 == 0) ? val[0] : val[2];
215         data[tmp2 + 2 * j + 1] = val[1];
216       }
217       data += stride;
218     }
219   } else {
220     data += stride * height;
221   }
222
223   for (i = 0; i < bottom; i++) {
224     for (j = 0; j < real_width; j++) {
225       data[2 * j] = (j % 2 == 0) ? val[0] : val[2];
226       data[2 * j + 1] = val[1];
227     }
228     data += stride;
229   }
230 }
231
232 void
233 vs_fill_borders_Y (const VSImage * dest, const uint8_t * val)
234 {
235   int i;
236   int top = dest->border_top, bottom = dest->border_bottom;
237   int left = dest->border_left, right = dest->border_right;
238   int width = dest->width;
239   int height = dest->height;
240   int real_width = dest->real_width;
241   int stride = dest->stride;
242   int tmp, tmp2;
243   uint8_t *data;
244
245   data = dest->real_pixels;
246   for (i = 0; i < top; i++) {
247     memset (data, *val, real_width);
248     data += stride;
249   }
250
251   if (left || right) {
252     tmp = height;
253     tmp2 = left + width;
254     for (i = 0; i < tmp; i++) {
255       memset (data, *val, left);
256       memset (data + tmp2, *val, right);
257       data += stride;
258     }
259   } else {
260     data += stride * height;
261   }
262
263   for (i = 0; i < bottom; i++) {
264     memset (data, *val, real_width);
265     data += stride;
266   }
267 }
268
269 void
270 vs_fill_borders_Y16 (const VSImage * dest, const uint16_t val)
271 {
272   int i;
273   int top = dest->border_top, bottom = dest->border_bottom;
274   int left = dest->border_left, right = dest->border_right;
275   int width = dest->width;
276   int height = dest->height;
277   int real_width = dest->real_width;
278   int stride = dest->stride;
279   int tmp, tmp2;
280   uint8_t *data;
281
282   data = dest->real_pixels;
283   for (i = 0; i < top; i++) {
284     video_scale_orc_splat_u16 ((uint16_t *) data, val, real_width);
285     data += stride;
286   }
287
288   if (left || right) {
289     tmp = height;
290     tmp2 = (left + width) * 2;
291     for (i = 0; i < tmp; i++) {
292       video_scale_orc_splat_u16 ((uint16_t *) data, val, left);
293       video_scale_orc_splat_u16 ((uint16_t *) (data + tmp2), val, right);
294       data += stride;
295     }
296   } else {
297     data += stride * height;
298   }
299
300   for (i = 0; i < bottom; i++) {
301     video_scale_orc_splat_u16 ((uint16_t *) data, val, real_width);
302     data += stride;
303   }
304 }
305
306 void
307 vs_fill_borders_RGB565 (const VSImage * dest, const uint8_t * val)
308 {
309   int i;
310   int top = dest->border_top, bottom = dest->border_bottom;
311   int left = dest->border_left, right = dest->border_right;
312   int width = dest->width;
313   int height = dest->height;
314   int real_width = dest->real_width;
315   int stride = dest->stride;
316   int tmp, tmp2;
317   uint8_t *data;
318   uint16_t v = READ_UINT16 (val);
319
320   data = dest->real_pixels;
321   for (i = 0; i < top; i++) {
322     video_scale_orc_splat_u16 ((uint16_t *) data, v, real_width);
323     data += stride;
324   }
325
326   if (left || right) {
327     tmp = height;
328     tmp2 = (left + width) * 2;
329     for (i = 0; i < tmp; i++) {
330       video_scale_orc_splat_u16 ((uint16_t *) data, v, left);
331       video_scale_orc_splat_u16 ((uint16_t *) (data + tmp2), v, right);
332       data += stride;
333     }
334   } else {
335     data += stride * height;
336   }
337
338   for (i = 0; i < bottom; i++) {
339     video_scale_orc_splat_u16 ((uint16_t *) data, v, real_width);
340     data += stride;
341   }
342 }
343
344 void
345 vs_fill_borders_RGB555 (const VSImage * dest, const uint8_t * val)
346 {
347   int i;
348   int top = dest->border_top, bottom = dest->border_bottom;
349   int left = dest->border_left, right = dest->border_right;
350   int width = dest->width;
351   int height = dest->height;
352   int real_width = dest->real_width;
353   int stride = dest->stride;
354   int tmp, tmp2;
355   uint8_t *data;
356   uint16_t v = READ_UINT16 (val);
357
358   data = dest->real_pixels;
359   for (i = 0; i < top; i++) {
360     video_scale_orc_splat_u16 ((uint16_t *) data, v, real_width);
361     data += stride;
362   }
363
364   if (left || right) {
365     tmp = height;
366     tmp2 = (left + width) * 2;
367     for (i = 0; i < tmp; i++) {
368       video_scale_orc_splat_u16 ((uint16_t *) data, v, left);
369       video_scale_orc_splat_u16 ((uint16_t *) (data + tmp2), v, right);
370       data += stride;
371     }
372   } else {
373     data += stride * height;
374   }
375
376   for (i = 0; i < bottom; i++) {
377     video_scale_orc_splat_u16 ((uint16_t *) data, v, real_width);
378     data += stride;
379   }
380 }
381
382 void
383 vs_fill_borders_AYUV64 (const VSImage * dest, const uint8_t * val)
384 {
385   int i;
386   int top = dest->border_top, bottom = dest->border_bottom;
387   int left = dest->border_left, right = dest->border_right;
388   int width = dest->width;
389   int height = dest->height;
390   int real_width = dest->real_width;
391   int stride = dest->stride;
392   int tmp, tmp2;
393   uint8_t *data;
394   uint64_t v;
395
396   v = (((guint32) val[0]) << 8) | (((guint32) val[1]) << 24) |
397       (((guint64) val[2]) << 40) | (((guint64) val[3]) << 56);
398
399   data = dest->real_pixels;
400   for (i = 0; i < top; i++) {
401     video_scale_orc_splat_u64 ((uint64_t *) data, v, real_width);
402     data += stride;
403   }
404
405   if (left || right) {
406     tmp = height;
407     tmp2 = (left + width) * 8;
408     for (i = 0; i < tmp; i++) {
409       video_scale_orc_splat_u64 ((uint64_t *) data, v, left);
410       video_scale_orc_splat_u64 ((uint64_t *) (data + tmp2), v, right);
411       data += stride;
412     }
413   } else {
414     data += stride * height;
415   }
416
417   for (i = 0; i < bottom; i++) {
418     video_scale_orc_splat_u64 ((uint64_t *) data, v, real_width);
419     data += stride;
420   }
421 }