swscale: do not forget to swap data in formats with different endianness
[libav.git] / libswscale / input.c
1 /*
2 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <assert.h>
22 #include <math.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "libavutil/avutil.h"
28 #include "libavutil/bswap.h"
29 #include "libavutil/cpu.h"
30 #include "libavutil/intreadwrite.h"
31 #include "libavutil/mathematics.h"
32 #include "libavutil/pixdesc.h"
33 #include "config.h"
34 #include "rgb2rgb.h"
35 #include "swscale.h"
36 #include "swscale_internal.h"
37
38 #define RGB2YUV_SHIFT 15
39 #define BY ((int)(0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
40 #define BV (-(int)(0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
41 #define BU ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
42 #define GY ((int)(0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
43 #define GV (-(int)(0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
44 #define GU (-(int)(0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
45 #define RY ((int)(0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
46 #define RV ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
47 #define RU (-(int)(0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
48
49 #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos))
50
51 #define r ((origin == AV_PIX_FMT_BGR48BE || origin == AV_PIX_FMT_BGR48LE) ? b_r : r_b)
52 #define b ((origin == AV_PIX_FMT_BGR48BE || origin == AV_PIX_FMT_BGR48LE) ? r_b : b_r)
53
54 static av_always_inline void rgb48ToY_c_template(uint16_t *dst,
55 const uint16_t *src, int width,
56 enum AVPixelFormat origin)
57 {
58 int i;
59 for (i = 0; i < width; i++) {
60 unsigned int r_b = input_pixel(&src[i * 3 + 0]);
61 unsigned int g = input_pixel(&src[i * 3 + 1]);
62 unsigned int b_r = input_pixel(&src[i * 3 + 2]);
63
64 dst[i] = (RY * r + GY * g + BY * b + (0x2001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
65 }
66 }
67
68 static av_always_inline void rgb48ToUV_c_template(uint16_t *dstU,
69 uint16_t *dstV,
70 const uint16_t *src1,
71 const uint16_t *src2,
72 int width,
73 enum AVPixelFormat origin)
74 {
75 int i;
76 assert(src1 == src2);
77 for (i = 0; i < width; i++) {
78 int r_b = input_pixel(&src1[i * 3 + 0]);
79 int g = input_pixel(&src1[i * 3 + 1]);
80 int b_r = input_pixel(&src1[i * 3 + 2]);
81
82 dstU[i] = (RU * r + GU * g + BU * b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
83 dstV[i] = (RV * r + GV * g + BV * b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
84 }
85 }
86
87 static av_always_inline void rgb48ToUV_half_c_template(uint16_t *dstU,
88 uint16_t *dstV,
89 const uint16_t *src1,
90 const uint16_t *src2,
91 int width,
92 enum AVPixelFormat origin)
93 {
94 int i;
95 assert(src1 == src2);
96 for (i = 0; i < width; i++) {
97 int r_b = (input_pixel(&src1[6 * i + 0]) +
98 input_pixel(&src1[6 * i + 3]) + 1) >> 1;
99 int g = (input_pixel(&src1[6 * i + 1]) +
100 input_pixel(&src1[6 * i + 4]) + 1) >> 1;
101 int b_r = (input_pixel(&src1[6 * i + 2]) +
102 input_pixel(&src1[6 * i + 5]) + 1) >> 1;
103
104 dstU[i] = (RU * r + GU * g + BU * b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
105 dstV[i] = (RV * r + GV * g + BV * b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
106 }
107 }
108
109 #undef r
110 #undef b
111 #undef input_pixel
112
113 #define rgb48funcs(pattern, BE_LE, origin) \
114 static void pattern ## 48 ## BE_LE ## ToY_c(uint8_t *_dst, \
115 const uint8_t *_src, \
116 int width, \
117 uint32_t *unused) \
118 { \
119 const uint16_t *src = (const uint16_t *)_src; \
120 uint16_t *dst = (uint16_t *)_dst; \
121 rgb48ToY_c_template(dst, src, width, origin); \
122 } \
123 \
124 static void pattern ## 48 ## BE_LE ## ToUV_c(uint8_t *_dstU, \
125 uint8_t *_dstV, \
126 const uint8_t *_src1, \
127 const uint8_t *_src2, \
128 int width, \
129 uint32_t *unused) \
130 { \
131 const uint16_t *src1 = (const uint16_t *)_src1, \
132 *src2 = (const uint16_t *)_src2; \
133 uint16_t *dstU = (uint16_t *)_dstU, \
134 *dstV = (uint16_t *)_dstV; \
135 rgb48ToUV_c_template(dstU, dstV, src1, src2, width, origin); \
136 } \
137 \
138 static void pattern ## 48 ## BE_LE ## ToUV_half_c(uint8_t *_dstU, \
139 uint8_t *_dstV, \
140 const uint8_t *_src1, \
141 const uint8_t *_src2, \
142 int width, \
143 uint32_t *unused) \
144 { \
145 const uint16_t *src1 = (const uint16_t *)_src1, \
146 *src2 = (const uint16_t *)_src2; \
147 uint16_t *dstU = (uint16_t *)_dstU, \
148 *dstV = (uint16_t *)_dstV; \
149 rgb48ToUV_half_c_template(dstU, dstV, src1, src2, width, origin); \
150 }
151
152 rgb48funcs(rgb, LE, AV_PIX_FMT_RGB48LE)
153 rgb48funcs(rgb, BE, AV_PIX_FMT_RGB48BE)
154 rgb48funcs(bgr, LE, AV_PIX_FMT_BGR48LE)
155 rgb48funcs(bgr, BE, AV_PIX_FMT_BGR48BE)
156
157 #define input_pixel(i) ((origin == AV_PIX_FMT_RGBA || \
158 origin == AV_PIX_FMT_BGRA || \
159 origin == AV_PIX_FMT_ARGB || \
160 origin == AV_PIX_FMT_ABGR) \
161 ? AV_RN32A(&src[(i) * 4]) \
162 : (isBE(origin) ? AV_RB16(&src[(i) * 2]) \
163 : AV_RL16(&src[(i) * 2])))
164
165 static av_always_inline void rgb16_32ToY_c_template(uint8_t *dst,
166 const uint8_t *src,
167 int width,
168 enum AVPixelFormat origin,
169 int shr, int shg,
170 int shb, int shp,
171 int maskr, int maskg,
172 int maskb, int rsh,
173 int gsh, int bsh, int S)
174 {
175 const int ry = RY << rsh, gy = GY << gsh, by = BY << bsh;
176 const unsigned rnd = 33u << (S - 1);
177 int i;
178
179 for (i = 0; i < width; i++) {
180 int px = input_pixel(i) >> shp;
181 int b = (px & maskb) >> shb;
182 int g = (px & maskg) >> shg;
183 int r = (px & maskr) >> shr;
184
185 dst[i] = (ry * r + gy * g + by * b + rnd) >> S;
186 }
187 }
188
189 static av_always_inline void rgb16_32ToUV_c_template(uint8_t *dstU,
190 uint8_t *dstV,
191 const uint8_t *src,
192 int width,
193 enum AVPixelFormat origin,
194 int shr, int shg,
195 int shb, int shp,
196 int maskr, int maskg,
197 int maskb, int rsh,
198 int gsh, int bsh, int S)
199 {
200 const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh,
201 rv = RV << rsh, gv = GV << gsh, bv = BV << bsh;
202 const unsigned rnd = 257u << (S - 1);
203 int i;
204
205 for (i = 0; i < width; i++) {
206 int px = input_pixel(i) >> shp;
207 int b = (px & maskb) >> shb;
208 int g = (px & maskg) >> shg;
209 int r = (px & maskr) >> shr;
210
211 dstU[i] = (ru * r + gu * g + bu * b + rnd) >> S;
212 dstV[i] = (rv * r + gv * g + bv * b + rnd) >> S;
213 }
214 }
215
216 static av_always_inline void rgb16_32ToUV_half_c_template(uint8_t *dstU,
217 uint8_t *dstV,
218 const uint8_t *src,
219 int width,
220 enum AVPixelFormat origin,
221 int shr, int shg,
222 int shb, int shp,
223 int maskr, int maskg,
224 int maskb, int rsh,
225 int gsh, int bsh, int S)
226 {
227 const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh,
228 rv = RV << rsh, gv = GV << gsh, bv = BV << bsh,
229 maskgx = ~(maskr | maskb);
230 const unsigned rnd = 257u << S;
231 int i;
232
233 maskr |= maskr << 1;
234 maskb |= maskb << 1;
235 maskg |= maskg << 1;
236 for (i = 0; i < width; i++) {
237 int px0 = input_pixel(2 * i + 0) >> shp;
238 int px1 = input_pixel(2 * i + 1) >> shp;
239 int b, r, g = (px0 & maskgx) + (px1 & maskgx);
240 int rb = px0 + px1 - g;
241
242 b = (rb & maskb) >> shb;
243 if (shp ||
244 origin == AV_PIX_FMT_BGR565LE || origin == AV_PIX_FMT_BGR565BE ||
245 origin == AV_PIX_FMT_RGB565LE || origin == AV_PIX_FMT_RGB565BE) {
246 g >>= shg;
247 } else {
248 g = (g & maskg) >> shg;
249 }
250 r = (rb & maskr) >> shr;
251
252 dstU[i] = (ru * r + gu * g + bu * b + rnd) >> (S + 1);
253 dstV[i] = (rv * r + gv * g + bv * b + rnd) >> (S + 1);
254 }
255 }
256
257 #undef input_pixel
258
259 #define rgb16_32_wrapper(fmt, name, shr, shg, shb, shp, maskr, \
260 maskg, maskb, rsh, gsh, bsh, S) \
261 static void name ## ToY_c(uint8_t *dst, const uint8_t *src, \
262 int width, uint32_t *unused) \
263 { \
264 rgb16_32ToY_c_template(dst, src, width, fmt, shr, shg, shb, shp, \
265 maskr, maskg, maskb, rsh, gsh, bsh, S); \
266 } \
267 \
268 static void name ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
269 const uint8_t *src, const uint8_t *dummy, \
270 int width, uint32_t *unused) \
271 { \
272 rgb16_32ToUV_c_template(dstU, dstV, src, width, fmt, \
273 shr, shg, shb, shp, \
274 maskr, maskg, maskb, rsh, gsh, bsh, S); \
275 } \
276 \
277 static void name ## ToUV_half_c(uint8_t *dstU, uint8_t *dstV, \
278 const uint8_t *src, \
279 const uint8_t *dummy, \
280 int width, uint32_t *unused) \
281 { \
282 rgb16_32ToUV_half_c_template(dstU, dstV, src, width, fmt, \
283 shr, shg, shb, shp, \
284 maskr, maskg, maskb, \
285 rsh, gsh, bsh, S); \
286 }
287
288 rgb16_32_wrapper(AV_PIX_FMT_BGR32, bgr32, 16, 0, 0, 0, 0xFF0000, 0xFF00, 0x00FF, 8, 0, 8, RGB2YUV_SHIFT + 8)
289 rgb16_32_wrapper(AV_PIX_FMT_BGR32_1, bgr321, 16, 0, 0, 8, 0xFF0000, 0xFF00, 0x00FF, 8, 0, 8, RGB2YUV_SHIFT + 8)
290 rgb16_32_wrapper(AV_PIX_FMT_RGB32, rgb32, 0, 0, 16, 0, 0x00FF, 0xFF00, 0xFF0000, 8, 0, 8, RGB2YUV_SHIFT + 8)
291 rgb16_32_wrapper(AV_PIX_FMT_RGB32_1, rgb321, 0, 0, 16, 8, 0x00FF, 0xFF00, 0xFF0000, 8, 0, 8, RGB2YUV_SHIFT + 8)
292 rgb16_32_wrapper(AV_PIX_FMT_BGR565LE, bgr16le, 0, 0, 0, 0, 0x001F, 0x07E0, 0xF800, 11, 5, 0, RGB2YUV_SHIFT + 8)
293 rgb16_32_wrapper(AV_PIX_FMT_BGR555LE, bgr15le, 0, 0, 0, 0, 0x001F, 0x03E0, 0x7C00, 10, 5, 0, RGB2YUV_SHIFT + 7)
294 rgb16_32_wrapper(AV_PIX_FMT_BGR444LE, bgr12le, 0, 0, 0, 0, 0x000F, 0x00F0, 0x0F00, 8, 4, 0, RGB2YUV_SHIFT + 4)
295 rgb16_32_wrapper(AV_PIX_FMT_RGB565LE, rgb16le, 0, 0, 0, 0, 0xF800, 0x07E0, 0x001F, 0, 5, 11, RGB2YUV_SHIFT + 8)
296 rgb16_32_wrapper(AV_PIX_FMT_RGB555LE, rgb15le, 0, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, 0, 5, 10, RGB2YUV_SHIFT + 7)
297 rgb16_32_wrapper(AV_PIX_FMT_RGB444LE, rgb12le, 0, 0, 0, 0, 0x0F00, 0x00F0, 0x000F, 0, 4, 8, RGB2YUV_SHIFT + 4)
298 rgb16_32_wrapper(AV_PIX_FMT_BGR565BE, bgr16be, 0, 0, 0, 0, 0x001F, 0x07E0, 0xF800, 11, 5, 0, RGB2YUV_SHIFT + 8)
299 rgb16_32_wrapper(AV_PIX_FMT_BGR555BE, bgr15be, 0, 0, 0, 0, 0x001F, 0x03E0, 0x7C00, 10, 5, 0, RGB2YUV_SHIFT + 7)
300 rgb16_32_wrapper(AV_PIX_FMT_BGR444BE, bgr12be, 0, 0, 0, 0, 0x000F, 0x00F0, 0x0F00, 8, 4, 0, RGB2YUV_SHIFT + 4)
301 rgb16_32_wrapper(AV_PIX_FMT_RGB565BE, rgb16be, 0, 0, 0, 0, 0xF800, 0x07E0, 0x001F, 0, 5, 11, RGB2YUV_SHIFT + 8)
302 rgb16_32_wrapper(AV_PIX_FMT_RGB555BE, rgb15be, 0, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, 0, 5, 10, RGB2YUV_SHIFT + 7)
303 rgb16_32_wrapper(AV_PIX_FMT_RGB444BE, rgb12be, 0, 0, 0, 0, 0x0F00, 0x00F0, 0x000F, 0, 4, 8, RGB2YUV_SHIFT + 4)
304
305 static void abgrToA_c(uint8_t *dst, const uint8_t *src, int width,
306 uint32_t *unused)
307 {
308 int i;
309 for (i = 0; i < width; i++)
310 dst[i] = src[4 * i];
311 }
312
313 static void rgbaToA_c(uint8_t *dst, const uint8_t *src, int width,
314 uint32_t *unused)
315 {
316 int i;
317 for (i = 0; i < width; i++)
318 dst[i] = src[4 * i + 3];
319 }
320
321 static void palToY_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *pal)
322 {
323 int i;
324 for (i = 0; i < width; i++) {
325 int d = src[i];
326
327 dst[i] = pal[d] & 0xFF;
328 }
329 }
330
331 static void palToUV_c(uint8_t *dstU, uint8_t *dstV,
332 const uint8_t *src1, const uint8_t *src2,
333 int width, uint32_t *pal)
334 {
335 int i;
336 assert(src1 == src2);
337 for (i = 0; i < width; i++) {
338 int p = pal[src1[i]];
339
340 dstU[i] = p >> 8;
341 dstV[i] = p >> 16;
342 }
343 }
344
345 static void monowhite2Y_c(uint8_t *dst, const uint8_t *src,
346 int width, uint32_t *unused)
347 {
348 int i, j;
349 width = (width + 7) >> 3;
350 for (i = 0; i < width; i++) {
351 int d = ~src[i];
352 for (j = 0; j < 8; j++)
353 dst[8 * i + j] = ((d >> (7 - j)) & 1) * 255;
354 }
355 }
356
357 static void monoblack2Y_c(uint8_t *dst, const uint8_t *src,
358 int width, uint32_t *unused)
359 {
360 int i, j;
361 width = (width + 7) >> 3;
362 for (i = 0; i < width; i++) {
363 int d = src[i];
364 for (j = 0; j < 8; j++)
365 dst[8 * i + j] = ((d >> (7 - j)) & 1) * 255;
366 }
367 }
368
369 static void yuy2ToY_c(uint8_t *dst, const uint8_t *src, int width,
370 uint32_t *unused)
371 {
372 int i;
373 for (i = 0; i < width; i++)
374 dst[i] = src[2 * i];
375 }
376
377 static void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
378 const uint8_t *src2, int width, uint32_t *unused)
379 {
380 int i;
381 for (i = 0; i < width; i++) {
382 dstU[i] = src1[4 * i + 1];
383 dstV[i] = src1[4 * i + 3];
384 }
385 assert(src1 == src2);
386 }
387
388 static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, int width,
389 uint32_t *unused)
390 {
391 int i;
392 const uint16_t *src = (const uint16_t *)_src;
393 uint16_t *dst = (uint16_t *)_dst;
394 for (i = 0; i < width; i++)
395 dst[i] = av_bswap16(src[i]);
396 }
397
398 static void bswap16UV_c(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src1,
399 const uint8_t *_src2, int width, uint32_t *unused)
400 {
401 int i;
402 const uint16_t *src1 = (const uint16_t *)_src1,
403 *src2 = (const uint16_t *)_src2;
404 uint16_t *dstU = (uint16_t *)_dstU, *dstV = (uint16_t *)_dstV;
405 for (i = 0; i < width; i++) {
406 dstU[i] = av_bswap16(src1[i]);
407 dstV[i] = av_bswap16(src2[i]);
408 }
409 }
410
411 /* This is almost identical to the previous, end exists only because
412 * yuy2ToY/UV)(dst, src + 1, ...) would have 100% unaligned accesses. */
413 static void uyvyToY_c(uint8_t *dst, const uint8_t *src, int width,
414 uint32_t *unused)
415 {
416 int i;
417 for (i = 0; i < width; i++)
418 dst[i] = src[2 * i + 1];
419 }
420
421 static void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
422 const uint8_t *src2, int width, uint32_t *unused)
423 {
424 int i;
425 for (i = 0; i < width; i++) {
426 dstU[i] = src1[4 * i + 0];
427 dstV[i] = src1[4 * i + 2];
428 }
429 assert(src1 == src2);
430 }
431
432 static av_always_inline void nvXXtoUV_c(uint8_t *dst1, uint8_t *dst2,
433 const uint8_t *src, int width)
434 {
435 int i;
436 for (i = 0; i < width; i++) {
437 dst1[i] = src[2 * i + 0];
438 dst2[i] = src[2 * i + 1];
439 }
440 }
441
442 static void nv12ToUV_c(uint8_t *dstU, uint8_t *dstV,
443 const uint8_t *src1, const uint8_t *src2,
444 int width, uint32_t *unused)
445 {
446 nvXXtoUV_c(dstU, dstV, src1, width);
447 }
448
449 static void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
450 const uint8_t *src1, const uint8_t *src2,
451 int width, uint32_t *unused)
452 {
453 nvXXtoUV_c(dstV, dstU, src1, width);
454 }
455
456 #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos))
457
458 static void bgr24ToY_c(uint8_t *dst, const uint8_t *src,
459 int width, uint32_t *unused)
460 {
461 int i;
462 for (i = 0; i < width; i++) {
463 int b = src[i * 3 + 0];
464 int g = src[i * 3 + 1];
465 int r = src[i * 3 + 2];
466
467 dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
468 }
469 }
470
471 static void bgr24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
472 const uint8_t *src2, int width, uint32_t *unused)
473 {
474 int i;
475 for (i = 0; i < width; i++) {
476 int b = src1[3 * i + 0];
477 int g = src1[3 * i + 1];
478 int r = src1[3 * i + 2];
479
480 dstU[i] = (RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
481 dstV[i] = (RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
482 }
483 assert(src1 == src2);
484 }
485
486 static void bgr24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
487 const uint8_t *src2, int width, uint32_t *unused)
488 {
489 int i;
490 for (i = 0; i < width; i++) {
491 int b = src1[6 * i + 0] + src1[6 * i + 3];
492 int g = src1[6 * i + 1] + src1[6 * i + 4];
493 int r = src1[6 * i + 2] + src1[6 * i + 5];
494
495 dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
496 dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
497 }
498 assert(src1 == src2);
499 }
500
501 static void rgb24ToY_c(uint8_t *dst, const uint8_t *src, int width,
502 uint32_t *unused)
503 {
504 int i;
505 for (i = 0; i < width; i++) {
506 int r = src[i * 3 + 0];
507 int g = src[i * 3 + 1];
508 int b = src[i * 3 + 2];
509
510 dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
511 }
512 }
513
514 static void rgb24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
515 const uint8_t *src2, int width, uint32_t *unused)
516 {
517 int i;
518 assert(src1 == src2);
519 for (i = 0; i < width; i++) {
520 int r = src1[3 * i + 0];
521 int g = src1[3 * i + 1];
522 int b = src1[3 * i + 2];
523
524 dstU[i] = (RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
525 dstV[i] = (RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
526 }
527 }
528
529 static void rgb24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
530 const uint8_t *src2, int width, uint32_t *unused)
531 {
532 int i;
533 assert(src1 == src2);
534 for (i = 0; i < width; i++) {
535 int r = src1[6 * i + 0] + src1[6 * i + 3];
536 int g = src1[6 * i + 1] + src1[6 * i + 4];
537 int b = src1[6 * i + 2] + src1[6 * i + 5];
538
539 dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
540 dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
541 }
542 }
543
544 static void planar_rgb_to_y(uint8_t *dst, const uint8_t *src[4], int width)
545 {
546 int i;
547 for (i = 0; i < width; i++) {
548 int g = src[0][i];
549 int b = src[1][i];
550 int r = src[2][i];
551
552 dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
553 }
554 }
555
556 static void planar_rgb_to_uv(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width)
557 {
558 int i;
559 for (i = 0; i < width; i++) {
560 int g = src[0][i];
561 int b = src[1][i];
562 int r = src[2][i];
563
564 dstU[i] = (RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
565 dstV[i] = (RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT;
566 }
567 }
568
569 #define rdpx(src) \
570 is_be ? AV_RB16(src) : AV_RL16(src)
571 static av_always_inline void planar_rgb16_to_y(uint8_t *_dst, const uint8_t *_src[4],
572 int width, int bpc, int is_be)
573 {
574 int i;
575 const uint16_t **src = (const uint16_t **)_src;
576 uint16_t *dst = (uint16_t *)_dst;
577 for (i = 0; i < width; i++) {
578 int g = rdpx(src[0] + i);
579 int b = rdpx(src[1] + i);
580 int r = rdpx(src[2] + i);
581
582 dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT + bpc - 9))) >> RGB2YUV_SHIFT);
583 }
584 }
585
586 static void planar_rgb9le_to_y(uint8_t *dst, const uint8_t *src[4], int w)
587 {
588 planar_rgb16_to_y(dst, src, w, 9, 0);
589 }
590
591 static void planar_rgb9be_to_y(uint8_t *dst, const uint8_t *src[4], int w)
592 {
593 planar_rgb16_to_y(dst, src, w, 9, 1);
594 }
595
596 static void planar_rgb10le_to_y(uint8_t *dst, const uint8_t *src[4], int w)
597 {
598 planar_rgb16_to_y(dst, src, w, 10, 0);
599 }
600
601 static void planar_rgb10be_to_y(uint8_t *dst, const uint8_t *src[4], int w)
602 {
603 planar_rgb16_to_y(dst, src, w, 10, 1);
604 }
605
606 static void planar_rgb16le_to_y(uint8_t *dst, const uint8_t *src[4], int w)
607 {
608 planar_rgb16_to_y(dst, src, w, 16, 0);
609 }
610
611 static void planar_rgb16be_to_y(uint8_t *dst, const uint8_t *src[4], int w)
612 {
613 planar_rgb16_to_y(dst, src, w, 16, 1);
614 }
615
616 static av_always_inline void planar_rgb16_to_uv(uint8_t *_dstU, uint8_t *_dstV,
617 const uint8_t *_src[4], int width,
618 int bpc, int is_be)
619 {
620 int i;
621 const uint16_t **src = (const uint16_t **)_src;
622 uint16_t *dstU = (uint16_t *)_dstU;
623 uint16_t *dstV = (uint16_t *)_dstV;
624 for (i = 0; i < width; i++) {
625 int g = rdpx(src[0] + i);
626 int b = rdpx(src[1] + i);
627 int r = rdpx(src[2] + i);
628
629 dstU[i] = (RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT + bpc - 9))) >> RGB2YUV_SHIFT;
630 dstV[i] = (RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT + bpc - 9))) >> RGB2YUV_SHIFT;
631 }
632 }
633 #undef rdpx
634
635 static void planar_rgb9le_to_uv(uint8_t *dstU, uint8_t *dstV,
636 const uint8_t *src[4], int w)
637 {
638 planar_rgb16_to_uv(dstU, dstV, src, w, 9, 0);
639 }
640
641 static void planar_rgb9be_to_uv(uint8_t *dstU, uint8_t *dstV,
642 const uint8_t *src[4], int w)
643 {
644 planar_rgb16_to_uv(dstU, dstV, src, w, 9, 1);
645 }
646
647 static void planar_rgb10le_to_uv(uint8_t *dstU, uint8_t *dstV,
648 const uint8_t *src[4], int w)
649 {
650 planar_rgb16_to_uv(dstU, dstV, src, w, 10, 0);
651 }
652
653 static void planar_rgb10be_to_uv(uint8_t *dstU, uint8_t *dstV,
654 const uint8_t *src[4], int w)
655 {
656 planar_rgb16_to_uv(dstU, dstV, src, w, 10, 1);
657 }
658
659 static void planar_rgb16le_to_uv(uint8_t *dstU, uint8_t *dstV,
660 const uint8_t *src[4], int w)
661 {
662 planar_rgb16_to_uv(dstU, dstV, src, w, 16, 0);
663 }
664
665 static void planar_rgb16be_to_uv(uint8_t *dstU, uint8_t *dstV,
666 const uint8_t *src[4], int w)
667 {
668 planar_rgb16_to_uv(dstU, dstV, src, w, 16, 1);
669 }
670
671 av_cold void ff_sws_init_input_funcs(SwsContext *c)
672 {
673 enum AVPixelFormat srcFormat = c->srcFormat;
674
675 c->chrToYV12 = NULL;
676 switch (srcFormat) {
677 case AV_PIX_FMT_YUYV422:
678 c->chrToYV12 = yuy2ToUV_c;
679 break;
680 case AV_PIX_FMT_UYVY422:
681 c->chrToYV12 = uyvyToUV_c;
682 break;
683 case AV_PIX_FMT_NV12:
684 c->chrToYV12 = nv12ToUV_c;
685 break;
686 case AV_PIX_FMT_NV21:
687 c->chrToYV12 = nv21ToUV_c;
688 break;
689 case AV_PIX_FMT_RGB8:
690 case AV_PIX_FMT_BGR8:
691 case AV_PIX_FMT_PAL8:
692 case AV_PIX_FMT_BGR4_BYTE:
693 case AV_PIX_FMT_RGB4_BYTE:
694 c->chrToYV12 = palToUV_c;
695 break;
696 case AV_PIX_FMT_GBRP9LE:
697 c->readChrPlanar = planar_rgb9le_to_uv;
698 break;
699 case AV_PIX_FMT_GBRP10LE:
700 c->readChrPlanar = planar_rgb10le_to_uv;
701 break;
702 case AV_PIX_FMT_GBRP16LE:
703 c->readChrPlanar = planar_rgb16le_to_uv;
704 break;
705 case AV_PIX_FMT_GBRP9BE:
706 c->readChrPlanar = planar_rgb9be_to_uv;
707 break;
708 case AV_PIX_FMT_GBRP10BE:
709 c->readChrPlanar = planar_rgb10be_to_uv;
710 break;
711 case AV_PIX_FMT_GBRP16BE:
712 c->readChrPlanar = planar_rgb16be_to_uv;
713 break;
714 case AV_PIX_FMT_GBRP:
715 c->readChrPlanar = planar_rgb_to_uv;
716 break;
717 #if HAVE_BIGENDIAN
718 case AV_PIX_FMT_YUV444P9LE:
719 case AV_PIX_FMT_YUV422P9LE:
720 case AV_PIX_FMT_YUV420P9LE:
721 case AV_PIX_FMT_YUV422P10LE:
722 case AV_PIX_FMT_YUV444P10LE:
723 case AV_PIX_FMT_YUV420P10LE:
724 case AV_PIX_FMT_YUV420P16LE:
725 case AV_PIX_FMT_YUV422P16LE:
726 case AV_PIX_FMT_YUV444P16LE:
727 case AV_PIX_FMT_YUVA444P9LE:
728 case AV_PIX_FMT_YUVA422P9LE:
729 case AV_PIX_FMT_YUVA420P9LE:
730 case AV_PIX_FMT_YUVA422P10LE:
731 case AV_PIX_FMT_YUVA444P10LE:
732 case AV_PIX_FMT_YUVA420P10LE:
733 case AV_PIX_FMT_YUVA420P16LE:
734 case AV_PIX_FMT_YUVA422P16LE:
735 case AV_PIX_FMT_YUVA444P16LE:
736 c->chrToYV12 = bswap16UV_c;
737 break;
738 #else
739 case AV_PIX_FMT_YUV444P9BE:
740 case AV_PIX_FMT_YUV422P9BE:
741 case AV_PIX_FMT_YUV420P9BE:
742 case AV_PIX_FMT_YUV444P10BE:
743 case AV_PIX_FMT_YUV422P10BE:
744 case AV_PIX_FMT_YUV420P10BE:
745 case AV_PIX_FMT_YUV420P16BE:
746 case AV_PIX_FMT_YUV422P16BE:
747 case AV_PIX_FMT_YUV444P16BE:
748 case AV_PIX_FMT_YUVA444P9BE:
749 case AV_PIX_FMT_YUVA422P9BE:
750 case AV_PIX_FMT_YUVA420P9BE:
751 case AV_PIX_FMT_YUVA422P10BE:
752 case AV_PIX_FMT_YUVA444P10BE:
753 case AV_PIX_FMT_YUVA420P10BE:
754 case AV_PIX_FMT_YUVA420P16BE:
755 case AV_PIX_FMT_YUVA422P16BE:
756 case AV_PIX_FMT_YUVA444P16BE:
757 c->chrToYV12 = bswap16UV_c;
758 break;
759 #endif
760 }
761 if (c->chrSrcHSubSample) {
762 switch (srcFormat) {
763 case AV_PIX_FMT_RGB48BE:
764 c->chrToYV12 = rgb48BEToUV_half_c;
765 break;
766 case AV_PIX_FMT_RGB48LE:
767 c->chrToYV12 = rgb48LEToUV_half_c;
768 break;
769 case AV_PIX_FMT_BGR48BE:
770 c->chrToYV12 = bgr48BEToUV_half_c;
771 break;
772 case AV_PIX_FMT_BGR48LE:
773 c->chrToYV12 = bgr48LEToUV_half_c;
774 break;
775 case AV_PIX_FMT_RGB32:
776 c->chrToYV12 = bgr32ToUV_half_c;
777 break;
778 case AV_PIX_FMT_RGB32_1:
779 c->chrToYV12 = bgr321ToUV_half_c;
780 break;
781 case AV_PIX_FMT_BGR24:
782 c->chrToYV12 = bgr24ToUV_half_c;
783 break;
784 case AV_PIX_FMT_BGR565LE:
785 c->chrToYV12 = bgr16leToUV_half_c;
786 break;
787 case AV_PIX_FMT_BGR565BE:
788 c->chrToYV12 = bgr16beToUV_half_c;
789 break;
790 case AV_PIX_FMT_BGR555LE:
791 c->chrToYV12 = bgr15leToUV_half_c;
792 break;
793 case AV_PIX_FMT_BGR555BE:
794 c->chrToYV12 = bgr15beToUV_half_c;
795 break;
796 case AV_PIX_FMT_BGR444LE:
797 c->chrToYV12 = bgr12leToUV_half_c;
798 break;
799 case AV_PIX_FMT_BGR444BE:
800 c->chrToYV12 = bgr12beToUV_half_c;
801 break;
802 case AV_PIX_FMT_BGR32:
803 c->chrToYV12 = rgb32ToUV_half_c;
804 break;
805 case AV_PIX_FMT_BGR32_1:
806 c->chrToYV12 = rgb321ToUV_half_c;
807 break;
808 case AV_PIX_FMT_RGB24:
809 c->chrToYV12 = rgb24ToUV_half_c;
810 break;
811 case AV_PIX_FMT_RGB565LE:
812 c->chrToYV12 = rgb16leToUV_half_c;
813 break;
814 case AV_PIX_FMT_RGB565BE:
815 c->chrToYV12 = rgb16beToUV_half_c;
816 break;
817 case AV_PIX_FMT_RGB555LE:
818 c->chrToYV12 = rgb15leToUV_half_c;
819 break;
820 case AV_PIX_FMT_RGB555BE:
821 c->chrToYV12 = rgb15beToUV_half_c;
822 break;
823 case AV_PIX_FMT_RGB444LE:
824 c->chrToYV12 = rgb12leToUV_half_c;
825 break;
826 case AV_PIX_FMT_RGB444BE:
827 c->chrToYV12 = rgb12beToUV_half_c;
828 break;
829 }
830 } else {
831 switch (srcFormat) {
832 case AV_PIX_FMT_RGB48BE:
833 c->chrToYV12 = rgb48BEToUV_c;
834 break;
835 case AV_PIX_FMT_RGB48LE:
836 c->chrToYV12 = rgb48LEToUV_c;
837 break;
838 case AV_PIX_FMT_BGR48BE:
839 c->chrToYV12 = bgr48BEToUV_c;
840 break;
841 case AV_PIX_FMT_BGR48LE:
842 c->chrToYV12 = bgr48LEToUV_c;
843 break;
844 case AV_PIX_FMT_RGB32:
845 c->chrToYV12 = bgr32ToUV_c;
846 break;
847 case AV_PIX_FMT_RGB32_1:
848 c->chrToYV12 = bgr321ToUV_c;
849 break;
850 case AV_PIX_FMT_BGR24:
851 c->chrToYV12 = bgr24ToUV_c;
852 break;
853 case AV_PIX_FMT_BGR565LE:
854 c->chrToYV12 = bgr16leToUV_c;
855 break;
856 case AV_PIX_FMT_BGR565BE:
857 c->chrToYV12 = bgr16beToUV_c;
858 break;
859 case AV_PIX_FMT_BGR555LE:
860 c->chrToYV12 = bgr15leToUV_c;
861 break;
862 case AV_PIX_FMT_BGR555BE:
863 c->chrToYV12 = bgr15beToUV_c;
864 break;
865 case AV_PIX_FMT_BGR444LE:
866 c->chrToYV12 = bgr12leToUV_c;
867 break;
868 case AV_PIX_FMT_BGR444BE:
869 c->chrToYV12 = bgr12beToUV_c;
870 break;
871 case AV_PIX_FMT_BGR32:
872 c->chrToYV12 = rgb32ToUV_c;
873 break;
874 case AV_PIX_FMT_BGR32_1:
875 c->chrToYV12 = rgb321ToUV_c;
876 break;
877 case AV_PIX_FMT_RGB24:
878 c->chrToYV12 = rgb24ToUV_c;
879 break;
880 case AV_PIX_FMT_RGB565LE:
881 c->chrToYV12 = rgb16leToUV_c;
882 break;
883 case AV_PIX_FMT_RGB565BE:
884 c->chrToYV12 = rgb16beToUV_c;
885 break;
886 case AV_PIX_FMT_RGB555LE:
887 c->chrToYV12 = rgb15leToUV_c;
888 break;
889 case AV_PIX_FMT_RGB555BE:
890 c->chrToYV12 = rgb15beToUV_c;
891 break;
892 case AV_PIX_FMT_RGB444LE:
893 c->chrToYV12 = rgb12leToUV_c;
894 break;
895 case AV_PIX_FMT_RGB444BE:
896 c->chrToYV12 = rgb12beToUV_c;
897 break;
898 }
899 }
900
901 c->lumToYV12 = NULL;
902 c->alpToYV12 = NULL;
903 switch (srcFormat) {
904 case AV_PIX_FMT_GBRP9LE:
905 c->readLumPlanar = planar_rgb9le_to_y;
906 break;
907 case AV_PIX_FMT_GBRP10LE:
908 c->readLumPlanar = planar_rgb10le_to_y;
909 break;
910 case AV_PIX_FMT_GBRP16LE:
911 c->readLumPlanar = planar_rgb16le_to_y;
912 break;
913 case AV_PIX_FMT_GBRP9BE:
914 c->readLumPlanar = planar_rgb9be_to_y;
915 break;
916 case AV_PIX_FMT_GBRP10BE:
917 c->readLumPlanar = planar_rgb10be_to_y;
918 break;
919 case AV_PIX_FMT_GBRP16BE:
920 c->readLumPlanar = planar_rgb16be_to_y;
921 break;
922 case AV_PIX_FMT_GBRP:
923 c->readLumPlanar = planar_rgb_to_y;
924 break;
925 #if HAVE_BIGENDIAN
926 case AV_PIX_FMT_YUV444P9LE:
927 case AV_PIX_FMT_YUV422P9LE:
928 case AV_PIX_FMT_YUV420P9LE:
929 case AV_PIX_FMT_YUV444P10LE:
930 case AV_PIX_FMT_YUV422P10LE:
931 case AV_PIX_FMT_YUV420P10LE:
932 case AV_PIX_FMT_YUV420P16LE:
933 case AV_PIX_FMT_YUV422P16LE:
934 case AV_PIX_FMT_YUV444P16LE:
935 case AV_PIX_FMT_GRAY16LE:
936 c->lumToYV12 = bswap16Y_c;
937 break;
938 case AV_PIX_FMT_YUVA444P9LE:
939 case AV_PIX_FMT_YUVA422P9LE:
940 case AV_PIX_FMT_YUVA420P9LE:
941 case AV_PIX_FMT_YUVA444P10LE:
942 case AV_PIX_FMT_YUVA422P10LE:
943 case AV_PIX_FMT_YUVA420P10LE:
944 case AV_PIX_FMT_YUVA420P16LE:
945 case AV_PIX_FMT_YUVA422P16LE:
946 case AV_PIX_FMT_YUVA444P16LE:
947 c->lumToYV12 = bswap16Y_c;
948 c->alpToYV12 = bswap16Y_c;
949 break;
950 #else
951 case AV_PIX_FMT_YUV444P9BE:
952 case AV_PIX_FMT_YUV422P9BE:
953 case AV_PIX_FMT_YUV420P9BE:
954 case AV_PIX_FMT_YUV444P10BE:
955 case AV_PIX_FMT_YUV422P10BE:
956 case AV_PIX_FMT_YUV420P10BE:
957 case AV_PIX_FMT_YUV420P16BE:
958 case AV_PIX_FMT_YUV422P16BE:
959 case AV_PIX_FMT_YUV444P16BE:
960 case AV_PIX_FMT_GRAY16BE:
961 c->lumToYV12 = bswap16Y_c;
962 break;
963 case AV_PIX_FMT_YUVA444P9BE:
964 case AV_PIX_FMT_YUVA422P9BE:
965 case AV_PIX_FMT_YUVA420P9BE:
966 case AV_PIX_FMT_YUVA444P10BE:
967 case AV_PIX_FMT_YUVA422P10BE:
968 case AV_PIX_FMT_YUVA420P10BE:
969 case AV_PIX_FMT_YUVA420P16BE:
970 case AV_PIX_FMT_YUVA422P16BE:
971 case AV_PIX_FMT_YUVA444P16BE:
972 c->lumToYV12 = bswap16Y_c;
973 c->alpToYV12 = bswap16Y_c;
974 break;
975 #endif
976 case AV_PIX_FMT_YUYV422:
977 case AV_PIX_FMT_Y400A:
978 c->lumToYV12 = yuy2ToY_c;
979 break;
980 case AV_PIX_FMT_UYVY422:
981 c->lumToYV12 = uyvyToY_c;
982 break;
983 case AV_PIX_FMT_BGR24:
984 c->lumToYV12 = bgr24ToY_c;
985 break;
986 case AV_PIX_FMT_BGR565LE:
987 c->lumToYV12 = bgr16leToY_c;
988 break;
989 case AV_PIX_FMT_BGR565BE:
990 c->lumToYV12 = bgr16beToY_c;
991 break;
992 case AV_PIX_FMT_BGR555LE:
993 c->lumToYV12 = bgr15leToY_c;
994 break;
995 case AV_PIX_FMT_BGR555BE:
996 c->lumToYV12 = bgr15beToY_c;
997 break;
998 case AV_PIX_FMT_BGR444LE:
999 c->lumToYV12 = bgr12leToY_c;
1000 break;
1001 case AV_PIX_FMT_BGR444BE:
1002 c->lumToYV12 = bgr12beToY_c;
1003 break;
1004 case AV_PIX_FMT_RGB24:
1005 c->lumToYV12 = rgb24ToY_c;
1006 break;
1007 case AV_PIX_FMT_RGB565LE:
1008 c->lumToYV12 = rgb16leToY_c;
1009 break;
1010 case AV_PIX_FMT_RGB565BE:
1011 c->lumToYV12 = rgb16beToY_c;
1012 break;
1013 case AV_PIX_FMT_RGB555LE:
1014 c->lumToYV12 = rgb15leToY_c;
1015 break;
1016 case AV_PIX_FMT_RGB555BE:
1017 c->lumToYV12 = rgb15beToY_c;
1018 break;
1019 case AV_PIX_FMT_RGB444LE:
1020 c->lumToYV12 = rgb12leToY_c;
1021 break;
1022 case AV_PIX_FMT_RGB444BE:
1023 c->lumToYV12 = rgb12beToY_c;
1024 break;
1025 case AV_PIX_FMT_RGB8:
1026 case AV_PIX_FMT_BGR8:
1027 case AV_PIX_FMT_PAL8:
1028 case AV_PIX_FMT_BGR4_BYTE:
1029 case AV_PIX_FMT_RGB4_BYTE:
1030 c->lumToYV12 = palToY_c;
1031 break;
1032 case AV_PIX_FMT_MONOBLACK:
1033 c->lumToYV12 = monoblack2Y_c;
1034 break;
1035 case AV_PIX_FMT_MONOWHITE:
1036 c->lumToYV12 = monowhite2Y_c;
1037 break;
1038 case AV_PIX_FMT_RGB32:
1039 c->lumToYV12 = bgr32ToY_c;
1040 break;
1041 case AV_PIX_FMT_RGB32_1:
1042 c->lumToYV12 = bgr321ToY_c;
1043 break;
1044 case AV_PIX_FMT_BGR32:
1045 c->lumToYV12 = rgb32ToY_c;
1046 break;
1047 case AV_PIX_FMT_BGR32_1:
1048 c->lumToYV12 = rgb321ToY_c;
1049 break;
1050 case AV_PIX_FMT_RGB48BE:
1051 c->lumToYV12 = rgb48BEToY_c;
1052 break;
1053 case AV_PIX_FMT_RGB48LE:
1054 c->lumToYV12 = rgb48LEToY_c;
1055 break;
1056 case AV_PIX_FMT_BGR48BE:
1057 c->lumToYV12 = bgr48BEToY_c;
1058 break;
1059 case AV_PIX_FMT_BGR48LE:
1060 c->lumToYV12 = bgr48LEToY_c;
1061 break;
1062 }
1063 if (c->alpPixBuf) {
1064 switch (srcFormat) {
1065 case AV_PIX_FMT_BGRA:
1066 case AV_PIX_FMT_RGBA:
1067 c->alpToYV12 = rgbaToA_c;
1068 break;
1069 case AV_PIX_FMT_ABGR:
1070 case AV_PIX_FMT_ARGB:
1071 c->alpToYV12 = abgrToA_c;
1072 break;
1073 case AV_PIX_FMT_Y400A:
1074 c->alpToYV12 = uyvyToY_c;
1075 break;
1076 }
1077 }
1078 }