1 /**
2 * @file vconv.c Video Conversion
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6
7 #include <string.h>
8 #include <re.h>
9 #include <rem_vid.h>
10 #include <rem_dsp.h>
11 #include <rem_vidconv.h>
12
13
14 #if 0
15
16 /*
17 * The lookup tables are generated with the following code:
18 */
19
20 #define P 14
21
22 #define COEF_RV ((int32_t) (1.370705f * (float)(1 << P)))
23 #define COEF_GU ((int32_t) (-0.337633f * (float)(1 << P)))
24 #define COEF_GV ((int32_t) (-0.698001f * (float)(1 << P)))
25 #define COEF_BU ((int32_t) (1.732446f * (float)(1 << P)))
26
27 #define ERV(a) (COEF_RV * ((a) - 128))
28 #define EGU(a) (COEF_GU * ((a) - 128))
29 #define EGV(a) (COEF_GV * ((a) - 128))
30 #define EBU(a) (COEF_BU * ((a) - 128))
31
32
33 int16_t CRV[256];
34 int16_t CGU[256];
35 int16_t CGV[256];
36 int16_t CBU[256];
37
38
39 static void init_table(void)
40 {
41 int i;
42
43 for (i = 0; i < 256; ++i) {
44 CRV[i] = ERV(i) >> P;
45 CGU[i] = EGU(i) >> P;
46 CGV[i] = EGV(i) >> P;
47 CBU[i] = EBU(i) >> P;
48 }
49 }
50 #endif
51
52
53 static const int16_t CRV[256] = {
54 -176,-175,-173,-172,-170,-169,-168,-166,-165,-164,-162,-161,
55 -159,-158,-157,-155,-154,-153,-151,-150,-149,-147,-146,-144,
56 -143,-142,-140,-139,-138,-136,-135,-133,-132,-131,-129,-128,
57 -127,-125,-124,-122,-121,-120,-118,-117,-116,-114,-113,-112,
58 -110,-109,-107,-106,-105,-103,-102,-101, -99, -98, -96, -95,
59 -94, -92, -91, -90, -88, -87, -85, -84, -83, -81, -80, -79,
60 -77, -76, -75, -73, -72, -70, -69, -68, -66, -65, -64, -62,
61 -61, -59, -58, -57, -55, -54, -53, -51, -50, -48, -47, -46,
62 -44, -43, -42, -40, -39, -38, -36, -35, -33, -32, -31, -29,
63 -28, -27, -25, -24, -22, -21, -20, -18, -17, -16, -14, -13,
64 -11, -10, -9, -7, -6, -5, -3, -2, 0, 1, 2, 4,
65 5, 6, 8, 9, 10, 12, 13, 15, 16, 17, 19, 20,
66 21, 23, 24, 26, 27, 28, 30, 31, 32, 34, 35, 37,
67 38, 39, 41, 42, 43, 45, 46, 47, 49, 50, 52, 53,
68 54, 56, 57, 58, 60, 61, 63, 64, 65, 67, 68, 69,
69 71, 72, 74, 75, 76, 78, 79, 80, 82, 83, 84, 86,
70 87, 89, 90, 91, 93, 94, 95, 97, 98, 100, 101, 102,
71 104, 105, 106, 108, 109, 111, 112, 113, 115, 116, 117, 119,
72 120, 121, 123, 124, 126, 127, 128, 130, 131, 132, 134, 135,
73 137, 138, 139, 141, 142, 143, 145, 146, 148, 149, 150, 152,
74 153, 154, 156, 157, 158, 160, 161, 163, 164, 165, 167, 168,
75 169, 171, 172, 174};
76
77 static const int16_t CGU[256] = {
78 43, 42, 42, 42, 41, 41, 41, 40, 40, 40, 39, 39,
79 39, 38, 38, 38, 37, 37, 37, 36, 36, 36, 35, 35,
80 35, 34, 34, 34, 33, 33, 33, 32, 32, 32, 31, 31,
81 31, 30, 30, 30, 29, 29, 29, 28, 28, 28, 27, 27,
82 27, 26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 23,
83 22, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19,
84 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15,
85 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11,
86 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7,
87 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3,
88 2, 2, 2, 1, 1, 1, 0, 0, 0, -1, -1, -2,
89 -2, -2, -3, -3, -3, -4, -4, -4, -5, -5, -5, -6,
90 -6, -6, -7, -7, -7, -8, -8, -8, -9, -9, -9, -10,
91 -10, -10, -11, -11, -11, -12, -12, -12, -13, -13, -13, -14,
92 -14, -14, -15, -15, -15, -16, -16, -16, -17, -17, -17, -18,
93 -18, -18, -19, -19, -19, -20, -20, -20, -21, -21, -21, -22,
94 -22, -22, -23, -23, -23, -24, -24, -24, -25, -25, -25, -26,
95 -26, -26, -27, -27, -28, -28, -28, -29, -29, -29, -30, -30,
96 -30, -31, -31, -31, -32, -32, -32, -33, -33, -33, -34, -34,
97 -34, -35, -35, -35, -36, -36, -36, -37, -37, -37, -38, -38,
98 -38, -39, -39, -39, -40, -40, -40, -41, -41, -41, -42, -42,
99 -42, -43, -43, -43};
100
101 static const int16_t CGV[256] = {
102 89, 88, 87, 87, 86, 85, 85, 84, 83, 83, 82, 81,
103 80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 73, 73,
104 72, 71, 71, 70, 69, 69, 68, 67, 67, 66, 65, 64,
105 64, 63, 62, 62, 61, 60, 60, 59, 58, 57, 57, 56,
106 55, 55, 54, 53, 53, 52, 51, 50, 50, 49, 48, 48,
107 47, 46, 46, 45, 44, 43, 43, 42, 41, 41, 40, 39,
108 39, 38, 37, 36, 36, 35, 34, 34, 33, 32, 32, 31,
109 30, 30, 29, 28, 27, 27, 26, 25, 25, 24, 23, 23,
110 22, 21, 20, 20, 19, 18, 18, 17, 16, 16, 15, 14,
111 13, 13, 12, 11, 11, 10, 9, 9, 8, 7, 6, 6,
112 5, 4, 4, 3, 2, 2, 1, 0, 0, -1, -2, -3,
113 -3, -4, -5, -5, -6, -7, -7, -8, -9, -10, -10, -11,
114 -12, -12, -13, -14, -14, -15, -16, -17, -17, -18, -19, -19,
115 -20, -21, -21, -22, -23, -24, -24, -25, -26, -26, -27, -28,
116 -28, -29, -30, -31, -31, -32, -33, -33, -34, -35, -35, -36,
117 -37, -37, -38, -39, -40, -40, -41, -42, -42, -43, -44, -44,
118 -45, -46, -47, -47, -48, -49, -49, -50, -51, -51, -52, -53,
119 -54, -54, -55, -56, -56, -57, -58, -58, -59, -60, -61, -61,
120 -62, -63, -63, -64, -65, -65, -66, -67, -68, -68, -69, -70,
121 -70, -71, -72, -72, -73, -74, -74, -75, -76, -77, -77, -78,
122 -79, -79, -80, -81, -81, -82, -83, -84, -84, -85, -86, -86,
123 -87, -88, -88, -89};
124
125 static const int16_t CBU[256] = {
126 -222,-221,-219,-217,-215,-214,-212,-210,-208,-207,-205,-203,
127 -201,-200,-198,-196,-195,-193,-191,-189,-188,-186,-184,-182,
128 -181,-179,-177,-175,-174,-172,-170,-169,-167,-165,-163,-162,
129 -160,-158,-156,-155,-153,-151,-149,-148,-146,-144,-143,-141,
130 -139,-137,-136,-134,-132,-130,-129,-127,-125,-124,-122,-120,
131 -118,-117,-115,-113,-111,-110,-108,-106,-104,-103,-101, -99,
132 -98, -96, -94, -92, -91, -89, -87, -85, -84, -82, -80, -78,
133 -77, -75, -73, -72, -70, -68, -66, -65, -63, -61, -59, -58,
134 -56, -54, -52, -51, -49, -47, -46, -44, -42, -40, -39, -37,
135 -35, -33, -32, -30, -28, -26, -25, -23, -21, -20, -18, -16,
136 -14, -13, -11, -9, -7, -6, -4, -2, 0, 1, 3, 5,
137 6, 8, 10, 12, 13, 15, 17, 19, 20, 22, 24, 25,
138 27, 29, 31, 32, 34, 36, 38, 39, 41, 43, 45, 46,
139 48, 50, 51, 53, 55, 57, 58, 60, 62, 64, 65, 67,
140 69, 71, 72, 74, 76, 77, 79, 81, 83, 84, 86, 88,
141 90, 91, 93, 95, 97, 98, 100, 102, 103, 105, 107, 109,
142 110, 112, 114, 116, 117, 119, 121, 123, 124, 126, 128, 129,
143 131, 133, 135, 136, 138, 140, 142, 143, 145, 147, 148, 150,
144 152, 154, 155, 157, 159, 161, 162, 164, 166, 168, 169, 171,
145 173, 174, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192,
146 194, 195, 197, 199, 200, 202, 204, 206, 207, 209, 211, 213,
147 214, 216, 218, 220};
148
149
yuv2rgb(uint8_t * rgb,uint8_t y,int ruv,int guv,int buv)150 static inline void yuv2rgb(uint8_t *rgb, uint8_t y, int ruv, int guv, int buv)
151 {
152 *rgb++ = saturate_u8(y + buv);
153 *rgb++ = saturate_u8(y + guv);
154 *rgb++ = saturate_u8(y + ruv);
155 *rgb = 0;
156 }
157
158
yuv2rgb565(uint8_t * rgb,uint8_t y,int ruv,int guv,int buv)159 static inline void yuv2rgb565(uint8_t *rgb, uint8_t y,
160 int ruv, int guv, int buv)
161 {
162 int r = saturate_u8(y + ruv) >> 3;
163 int g = saturate_u8(y + guv) >> 2;
164 int b = saturate_u8(y + buv) >> 3;
165
166 rgb[1] = r << 3 | g >> 3;
167 rgb[0] = g << 5 | b;
168 }
169
170
yuv2rgb555(uint8_t * rgb,uint8_t y,int ruv,int guv,int buv)171 static inline void yuv2rgb555(uint8_t *rgb, uint8_t y,
172 int ruv, int guv, int buv)
173 {
174 uint8_t r = saturate_u8(y + ruv) >> 3;
175 uint8_t g = saturate_u8(y + guv) >> 3;
176 uint8_t b = saturate_u8(y + buv) >> 3;
177
178 rgb[1] = r << 2 | g >> 3;
179 rgb[0] = g << 5 | b;
180 }
181
182
_yuv2rgb(uint8_t * rgb,uint8_t y,uint8_t u,uint8_t v)183 static inline void _yuv2rgb(uint8_t *rgb, uint8_t y, uint8_t u, uint8_t v)
184 {
185 int ruv, guv, buv;
186
187 ruv = CRV[v];
188 guv = CGV[v] + CGU[u];
189 buv = CBU[u];
190
191 yuv2rgb(rgb, y, ruv, guv, buv);
192 }
193
194
195 typedef void (line_h)(unsigned xoffs, unsigned width, double rw,
196 unsigned yd, unsigned ys, unsigned ys2,
197 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
198 unsigned lsd,
199 const uint8_t *sd0, const uint8_t *sd1,
200 const uint8_t *sd2, unsigned lss);
201
202
yuv420p_to_yuv420p(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)203 static void yuv420p_to_yuv420p(unsigned xoffs, unsigned width, double rw,
204 unsigned yd, unsigned ys, unsigned ys2,
205 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
206 unsigned lsd,
207 const uint8_t *ds0, const uint8_t *ds1,
208 const uint8_t *ds2, unsigned lss
209 )
210 {
211 unsigned x, xd, xs, xs2;
212 unsigned id, is;
213
214 for (x=0; x<width; x+=2) {
215
216 xd = x + xoffs;
217
218 xs = (unsigned)(x * rw);
219 xs2 = (unsigned)((x+1) * rw);
220
221 id = xd + yd*lsd;
222
223 dd0[id] = ds0[xs + ys*lss];
224 dd0[id+1] = ds0[xs2 + ys*lss];
225 dd0[id + lsd] = ds0[xs + ys2*lss];
226 dd0[id+1 + lsd] = ds0[xs2 + ys2*lss];
227
228 id = xd/2 + yd*lsd/4;
229 is = (xs>>1) + (ys>>1)*lss/2;
230
231 dd1[id] = ds1[is];
232 dd2[id] = ds2[is];
233 }
234 }
235
236
yuyv422_to_yuv420p(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * sd0,const uint8_t * sd1,const uint8_t * sd2,unsigned lss)237 static void yuyv422_to_yuv420p(unsigned xoffs, unsigned width, double rw,
238 unsigned yd, unsigned ys, unsigned ys2,
239 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
240 unsigned lsd,
241 const uint8_t *sd0, const uint8_t *sd1,
242 const uint8_t *sd2, unsigned lss
243 )
244 {
245 unsigned x, xd, xs;
246 unsigned id, is, is2;
247
248 (void)sd1;
249 (void)sd2;
250
251 for (x=0; x<width; x+=2) {
252
253 xd = x + xoffs;
254
255 xs = ((unsigned)(x * rw * 2)) & ~3;
256
257 id = xd + yd*lsd;
258 is = xs + ys*lss;
259 is2 = xs + ys2*lss;
260
261 dd0[id] = sd0[is];
262 dd0[id+1] = sd0[is + 2];
263 dd0[id + lsd] = sd0[is2];
264 dd0[id+1 + lsd] = sd0[is2 + 2];
265
266 id = xd/2 + yd*lsd/4;
267
268 dd1[id] = sd0[is + 1];
269 dd2[id] = sd0[is + 3];
270 }
271 }
272
273
uyvy422_to_yuv420p(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * sd0,const uint8_t * sd1,const uint8_t * sd2,unsigned lss)274 static void uyvy422_to_yuv420p(unsigned xoffs, unsigned width, double rw,
275 unsigned yd, unsigned ys, unsigned ys2,
276 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
277 unsigned lsd,
278 const uint8_t *sd0, const uint8_t *sd1,
279 const uint8_t *sd2, unsigned lss
280 )
281 {
282 unsigned x, xd, xs;
283 unsigned id, is, is2;
284
285 (void)sd1;
286 (void)sd2;
287
288 for (x=0; x<width; x+=2) {
289
290 xd = x + xoffs;
291
292 xs = ((unsigned)(x * rw * 2)) & ~3;
293
294 id = xd + yd*lsd;
295 is = xs + ys*lss;
296 is2 = xs + ys2*lss;
297
298 dd0[id] = sd0[is + 1];
299 dd0[id+1] = sd0[is + 3];
300 dd0[id + lsd] = sd0[is2 + 1];
301 dd0[id+1 + lsd] = sd0[is2 + 3];
302
303 id = xd/2 + yd*lsd/4;
304
305 dd1[id] = sd0[is + 0];
306 dd2[id] = sd0[is + 2];
307 }
308 }
309
310
rgb32_to_yuv420p(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)311 static void rgb32_to_yuv420p(unsigned xoffs, unsigned width, double rw,
312 unsigned yd, unsigned ys, unsigned ys2,
313 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
314 unsigned lsd,
315 const uint8_t *ds0, const uint8_t *ds1,
316 const uint8_t *ds2, unsigned lss
317 )
318 {
319 unsigned x, xd, xs, xs2;
320 unsigned id;
321
322 (void)ds1;
323 (void)ds2;
324
325 for (x=0; x<width; x+=2) {
326
327 uint32_t x0;
328 uint32_t x1;
329 uint32_t x2;
330 uint32_t x3;
331
332 xd = x + xoffs;
333
334 xs = 4 * ((unsigned)( x * rw));
335 xs2 = 4 * ((unsigned)((x+1) * rw));
336
337 id = xd + yd*lsd;
338
339 x0 = *(uint32_t *)(void *)&ds0[xs + ys*lss];
340 x1 = *(uint32_t *)(void *)&ds0[xs2 + ys*lss];
341 x2 = *(uint32_t *)(void *)&ds0[xs + ys2*lss];
342 x3 = *(uint32_t *)(void *)&ds0[xs2 + ys2*lss];
343
344 dd0[id] = rgb2y(x0 >> 16, x0 >> 8, x0);
345 dd0[id+1] = rgb2y(x1 >> 16, x1 >> 8, x1);
346 dd0[id + lsd] = rgb2y(x2 >> 16, x2 >> 8, x2);
347 dd0[id+1 + lsd] = rgb2y(x3 >> 16, x3 >> 8, x3);
348
349 id = xd/2 + yd*lsd/4;
350
351 dd1[id] = rgb2u(x0 >> 16, x0 >> 8, x0);
352 dd2[id] = rgb2v(x0 >> 16, x0 >> 8, x0);
353 }
354 }
355
356
rgb32_to_yuv444p(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)357 static void rgb32_to_yuv444p(unsigned xoffs, unsigned width, double rw,
358 unsigned yd, unsigned ys, unsigned ys2,
359 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
360 unsigned lsd,
361 const uint8_t *ds0, const uint8_t *ds1,
362 const uint8_t *ds2, unsigned lss
363 )
364 {
365 unsigned x, xd, xs;
366 unsigned id;
367
368 (void)ds1;
369 (void)ds2;
370
371 for (x=0; x<width; x++) {
372
373 uint32_t x0;
374 uint32_t x1;
375
376 xd = x + xoffs;
377
378 xs = 4 * ((unsigned)(x * rw));
379
380 id = xd + yd*lsd;
381
382 x0 = *(uint32_t *)(void *)&ds0[xs + ys *lss];
383 x1 = *(uint32_t *)(void *)&ds0[xs + ys2*lss];
384
385 dd0[id] = rgb2y(x0 >> 16, x0 >> 8, x0);
386 dd0[id + lsd] = rgb2y(x1 >> 16, x1 >> 8, x1);
387
388 dd1[id] = rgb2u(x0 >> 16, x0 >> 8, x0);
389 dd1[id + lsd] = rgb2u(x1 >> 16, x1 >> 8, x1);
390
391 dd2[id] = rgb2v(x0 >> 16, x0 >> 8, x0);
392 dd2[id + lsd] = rgb2v(x1 >> 16, x1 >> 8, x1);
393 }
394 }
395
396
yuv420p_to_rgb32(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)397 static void yuv420p_to_rgb32(unsigned xoffs, unsigned width, double rw,
398 unsigned yd, unsigned ys, unsigned ys2,
399 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
400 unsigned lsd,
401 const uint8_t *ds0, const uint8_t *ds1,
402 const uint8_t *ds2, unsigned lss)
403 {
404 unsigned x, xd, xs, xs2;
405 unsigned id, is;
406
407 (void)dd1;
408 (void)dd2;
409
410 for (x=0; x<width; x+=2) {
411
412 int ruv, guv, buv;
413 uint8_t u, v;
414
415 xd = (x + xoffs) * 4;
416
417 xs = (unsigned)(x * rw);
418 xs2 = (unsigned)((x+1) * rw);
419
420 id = (xd + yd*lsd);
421 is = (xs>>1) + (ys>>1)*lss/2;
422
423 u = ds1[is];
424 v = ds2[is];
425
426 ruv = CRV[v];
427 guv = CGV[v] + CGU[u];
428 buv = CBU[u];
429
430 yuv2rgb(&dd0[id], ds0[xs + ys*lss], ruv, guv, buv);
431 yuv2rgb(&dd0[id+4], ds0[xs2 + ys*lss], ruv, guv, buv);
432 yuv2rgb(&dd0[id + lsd], ds0[xs + ys2*lss], ruv, guv, buv);
433 yuv2rgb(&dd0[id+4 + lsd], ds0[xs2 + ys2*lss], ruv, guv, buv);
434 }
435 }
436
437
yuv420p_to_rgb565(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)438 static void yuv420p_to_rgb565(unsigned xoffs, unsigned width, double rw,
439 unsigned yd, unsigned ys, unsigned ys2,
440 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
441 unsigned lsd,
442 const uint8_t *ds0, const uint8_t *ds1,
443 const uint8_t *ds2, unsigned lss)
444 {
445 unsigned x, xd, xs, xs2;
446 unsigned id, is;
447
448 (void)dd1;
449 (void)dd2;
450
451 for (x=0; x<width; x+=2) {
452
453 int ruv, guv, buv;
454 uint8_t u, v;
455
456 xd = (x + xoffs) * 2;
457
458 xs = (unsigned)(x * rw);
459 xs2 = (unsigned)((x+1) * rw);
460
461 id = (xd + yd*lsd);
462 is = (xs>>1) + (ys>>1)*lss/2;
463
464 u = ds1[is];
465 v = ds2[is];
466
467 ruv = CRV[v];
468 guv = CGV[v] + CGU[u];
469 buv = CBU[u];
470
471 yuv2rgb565(&dd0[id], ds0[xs + ys*lss], ruv, guv,buv);
472 yuv2rgb565(&dd0[id+2], ds0[xs2 + ys*lss], ruv, guv,buv);
473 yuv2rgb565(&dd0[id + lsd], ds0[xs + ys2*lss], ruv, guv,buv);
474 yuv2rgb565(&dd0[id+2 + lsd], ds0[xs2 + ys2*lss], ruv, guv,buv);
475 }
476 }
477
478
yuv420p_to_rgb555(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)479 static void yuv420p_to_rgb555(unsigned xoffs, unsigned width, double rw,
480 unsigned yd, unsigned ys, unsigned ys2,
481 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
482 unsigned lsd,
483 const uint8_t *ds0, const uint8_t *ds1,
484 const uint8_t *ds2, unsigned lss)
485 {
486 unsigned x, xd, xs, xs2;
487 unsigned id, is;
488
489 (void)dd1;
490 (void)dd2;
491
492 for (x=0; x<width; x+=2) {
493
494 int ruv, guv, buv;
495 uint8_t u, v;
496
497 xd = (x + xoffs) * 2;
498
499 xs = (unsigned)(x * rw);
500 xs2 = (unsigned)((x+1) * rw);
501
502 id = (xd + yd*lsd);
503 is = (xs>>1) + (ys>>1)*lss/2;
504
505 u = ds1[is];
506 v = ds2[is];
507
508 ruv = CRV[v];
509 guv = CGV[v] + CGU[u];
510 buv = CBU[u];
511
512 yuv2rgb555(&dd0[id], ds0[xs + ys*lss], ruv, guv,buv);
513 yuv2rgb555(&dd0[id+2], ds0[xs2 + ys*lss], ruv, guv,buv);
514 yuv2rgb555(&dd0[id + lsd], ds0[xs + ys2*lss], ruv, guv,buv);
515 yuv2rgb555(&dd0[id+2 + lsd], ds0[xs2 + ys2*lss], ruv, guv,buv);
516 }
517 }
518
519
nv12_to_yuv420p(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)520 static void nv12_to_yuv420p(unsigned xoffs, unsigned width, double rw,
521 unsigned yd, unsigned ys, unsigned ys2,
522 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
523 unsigned lsd,
524 const uint8_t *ds0, const uint8_t *ds1,
525 const uint8_t *ds2, unsigned lss
526 )
527 {
528 unsigned x, xd, xs, xs2;
529 unsigned id, is;
530
531 (void)ds2;
532
533 for (x=0; x<width; x+=2) {
534
535 xd = x + xoffs;
536
537 xs = (unsigned)(x * rw);
538 xs2 = (unsigned)((x+1) * rw);
539
540 id = xd + yd*lsd;
541
542 dd0[id] = ds0[xs + ys*lss];
543 dd0[id+1] = ds0[xs2 + ys*lss];
544 dd0[id + lsd] = ds0[xs + ys2*lss];
545 dd0[id+1 + lsd] = ds0[xs2 + ys2*lss];
546
547 id = (xd>>1) + (yd>>1)*lsd/2;
548 is = xs/2 + ys*lss/4;
549
550 dd1[id] = ds1[2*is];
551 dd2[id] = ds1[2*is+1];
552 }
553 }
554
555
yuv420p_to_nv12(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)556 static void yuv420p_to_nv12(unsigned xoffs, unsigned width, double rw,
557 unsigned yd, unsigned ys, unsigned ys2,
558 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
559 unsigned lsd,
560 const uint8_t *ds0, const uint8_t *ds1,
561 const uint8_t *ds2, unsigned lss
562 )
563 {
564 unsigned x, xd, xs, xs2;
565 unsigned id, is;
566
567 (void)dd2;
568
569 for (x=0; x<width; x+=2) {
570
571 xd = x + xoffs;
572
573 xs = (unsigned)(x * rw);
574 xs2 = (unsigned)((x+1) * rw);
575
576 id = xd + yd*lsd;
577
578 dd0[id] = ds0[xs + ys*lss];
579 dd0[id+1] = ds0[xs2 + ys*lss];
580 dd0[id + lsd] = ds0[xs + ys2*lss];
581 dd0[id+1 + lsd] = ds0[xs2 + ys2*lss];
582
583 id = xd/2 + yd*lsd/4;
584 is = (xs>>1) + (ys>>1)*lss/2;
585
586 dd1[2*id] = ds1[is];
587 dd1[2*id+1] = ds2[is];
588 }
589 }
590
591
nv21_to_yuv420p(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)592 static void nv21_to_yuv420p(unsigned xoffs, unsigned width, double rw,
593 unsigned yd, unsigned ys, unsigned ys2,
594 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
595 unsigned lsd,
596 const uint8_t *ds0, const uint8_t *ds1,
597 const uint8_t *ds2, unsigned lss
598 )
599 {
600 unsigned x, xd, xs, xs2;
601 unsigned id, is;
602
603 (void)ds2;
604
605 for (x=0; x<width; x+=2) {
606
607 xd = x + xoffs;
608
609 xs = (unsigned)(x * rw);
610 xs2 = (unsigned)((x+1) * rw);
611
612 id = xd + yd*lsd;
613
614 dd0[id] = ds0[xs + ys*lss];
615 dd0[id+1] = ds0[xs2 + ys*lss];
616 dd0[id + lsd] = ds0[xs + ys2*lss];
617 dd0[id+1 + lsd] = ds0[xs2 + ys2*lss];
618
619 id = xd/2 + yd*lsd/4;
620 is = ((xs>>1) + (ys>>1)*lss/2) & ~1;
621
622 dd2[id] = ds1[2*is];
623 dd1[id] = ds1[2*is+1];
624 }
625 }
626
627
yuv444p_to_rgb32(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)628 static void yuv444p_to_rgb32(unsigned xoffs, unsigned width, double rw,
629 unsigned yd, unsigned ys, unsigned ys2,
630 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
631 unsigned lsd,
632 const uint8_t *ds0, const uint8_t *ds1,
633 const uint8_t *ds2, unsigned lss)
634 {
635 unsigned x, xd, xs;
636 unsigned id;
637 unsigned is1, is2;
638
639 (void)dd1;
640 (void)dd2;
641
642 for (x=0; x<width; x++) {
643
644 xd = (x + xoffs) * 4;
645
646 xs = (unsigned)(x * rw);
647
648 id = xd + yd*lsd;
649
650 is1 = xs + ys *lss;
651 is2 = xs + ys2*lss;
652
653 _yuv2rgb(&dd0[id], ds0[is1], ds1[is1], ds2[is1]);
654 _yuv2rgb(&dd0[id + lsd], ds0[is2], ds1[is2], ds2[is2]);
655 }
656 }
657
658
nv12_to_rgb32(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)659 static void nv12_to_rgb32(unsigned xoffs, unsigned width, double rw,
660 unsigned yd, unsigned ys, unsigned ys2,
661 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
662 unsigned lsd,
663 const uint8_t *ds0, const uint8_t *ds1,
664 const uint8_t *ds2, unsigned lss
665 )
666 {
667 unsigned x, xd, xs, xs2;
668 unsigned id, is;
669
670 (void)ds2;
671 (void)dd1;
672 (void)dd2;
673
674 for (x=0; x<width; x+=2) {
675 int ruv, guv, buv;
676 uint8_t u, v;
677
678 xd = (x + xoffs) * 4;
679
680 xs = (unsigned)(x * rw);
681 xs2 = (unsigned)((x+1) * rw);
682
683 id = (xd + yd*lsd);
684 is = xs/2 + ys*lss/4;
685
686 u = ds1[2*is];
687 v = ds1[2*is+1];
688 ruv = CRV[v];
689 guv = CGV[v] + CGU[u];
690 buv = CBU[u];
691
692 yuv2rgb(&dd0[id], ds0[xs + ys*lss], ruv, guv, buv);
693 yuv2rgb(&dd0[id+4], ds0[xs2 + ys*lss], ruv, guv, buv);
694 yuv2rgb(&dd0[id + lsd], ds0[xs + ys2*lss], ruv, guv, buv);
695 yuv2rgb(&dd0[id+4 + lsd], ds0[xs2 + ys2*lss], ruv, guv, buv);
696 }
697 }
698
699
nv21_to_rgb32(unsigned xoffs,unsigned width,double rw,unsigned yd,unsigned ys,unsigned ys2,uint8_t * dd0,uint8_t * dd1,uint8_t * dd2,unsigned lsd,const uint8_t * ds0,const uint8_t * ds1,const uint8_t * ds2,unsigned lss)700 static void nv21_to_rgb32(unsigned xoffs, unsigned width, double rw,
701 unsigned yd, unsigned ys, unsigned ys2,
702 uint8_t *dd0, uint8_t *dd1, uint8_t *dd2,
703 unsigned lsd,
704 const uint8_t *ds0, const uint8_t *ds1,
705 const uint8_t *ds2, unsigned lss
706 )
707 {
708 unsigned x, xd, xs, xs2;
709 unsigned id, is;
710
711 (void)ds2;
712 (void)dd1;
713 (void)dd2;
714
715 for (x=0; x<width; x+=2) {
716 int ruv, guv, buv;
717 uint8_t u, v;
718
719 xd = (x + xoffs) * 4;
720
721 xs = (unsigned)(x * rw);
722 xs2 = (unsigned)((x+1) * rw);
723
724 id = (xd + yd*lsd);
725 is = xs/2 + ys*lss/4;
726
727 v = ds1[2*is];
728 u = ds1[2*is+1];
729 ruv = CRV[v];
730 guv = CGV[v] + CGU[u];
731 buv = CBU[u];
732
733 yuv2rgb(&dd0[id], ds0[xs + ys*lss], ruv, guv, buv);
734 yuv2rgb(&dd0[id+4], ds0[xs2 + ys*lss], ruv, guv, buv);
735 yuv2rgb(&dd0[id + lsd], ds0[xs + ys2*lss], ruv, guv, buv);
736 yuv2rgb(&dd0[id+4 + lsd], ds0[xs2 + ys2*lss], ruv, guv, buv);
737 }
738 }
739
740
741 #define MAX_SRC 10
742 #define MAX_DST 10
743
744
745 /**
746 * Pixel conversion table: [src][dst]
747 *
748 * @note Index must be aligned to values in enum vidfmt
749 */
750 static line_h *conv_table[MAX_SRC][MAX_DST] = {
751
752 /*
753 * Dst: YUV420P YUYV422 UYVY422 RGB32
754 */
755 {yuv420p_to_yuv420p, NULL, NULL, yuv420p_to_rgb32, NULL,
756 yuv420p_to_rgb565, yuv420p_to_rgb555, yuv420p_to_nv12},
757 {yuyv422_to_yuv420p, NULL, NULL, NULL, NULL, NULL, NULL},
758 {uyvy422_to_yuv420p, NULL, NULL, NULL, NULL, NULL, NULL},
759 {rgb32_to_yuv420p, NULL, NULL, NULL, NULL, NULL, NULL,
760 NULL, NULL, rgb32_to_yuv444p},
761 {rgb32_to_yuv420p, NULL, NULL, NULL, NULL, NULL, NULL},
762 {NULL, NULL, NULL, NULL, NULL, NULL, NULL},
763 {NULL, NULL, NULL, NULL, NULL, NULL, NULL},
764 {nv12_to_yuv420p, NULL, NULL, nv12_to_rgb32,
765 NULL, NULL, NULL},
766 {nv21_to_yuv420p, NULL, NULL, nv21_to_rgb32,
767 NULL, NULL, NULL},
768 {NULL, NULL, NULL, yuv444p_to_rgb32}
769 };
770
771
772 /**
773 * Convert a video frame from one pixel format to another pixel format
774 *
775 * Speed matches swscale: SWS_BILINEAR
776 *
777 * todo: optimize (check out SWS_FAST_BILINEAR)
778 *
779 * @param dst Destination video frame
780 * @param src Source video frame
781 * @param r Drawing area in destination frame, NULL means whole frame
782 */
vidconv(struct vidframe * dst,const struct vidframe * src,struct vidrect * r)783 void vidconv(struct vidframe *dst, const struct vidframe *src,
784 struct vidrect *r)
785 {
786 struct vidrect rdst;
787 unsigned yd, ys, ys2, lsd, lss, y;
788 const uint8_t *ds0, *ds1, *ds2;
789 uint8_t *dd0, *dd1, *dd2;
790 double rw, rh;
791 line_h *lineh = NULL;
792
793 if (!vidframe_isvalid(dst) || !vidframe_isvalid(src))
794 return;
795
796 if (src->fmt < MAX_SRC && dst->fmt < MAX_DST) {
797
798 /* Lookup conversion function */
799 lineh = conv_table[src->fmt][dst->fmt];
800 }
801 if (!lineh) {
802 (void)re_printf("vidconv: no pixel converter found for"
803 " %s -> %s\n", vidfmt_name(src->fmt),
804 vidfmt_name(dst->fmt));
805 return;
806 }
807
808 if (r) {
809 r->x &= ~1;
810 r->y &= ~1;
811 r->w &= ~1;
812 r->h &= ~1;
813
814 if ((r->x + r->w) > dst->size.w ||
815 (r->y + r->h) > dst->size.h) {
816 (void)re_printf("vidconv: out of bounds (%u x %u)\n",
817 dst->size.w, dst->size.h);
818 return;
819 }
820 }
821 else {
822 rdst.x = rdst.y = 0;
823 rdst.w = dst->size.w & ~1;
824 rdst.h = dst->size.h & ~1;
825 r = &rdst;
826 }
827
828 rw = (double)src->size.w / (double)r->w;
829 rh = (double)src->size.h / (double)r->h;
830
831 lsd = dst->linesize[0];
832 lss = src->linesize[0];
833
834 dd0 = dst->data[0];
835 dd1 = dst->data[1];
836 dd2 = dst->data[2];
837
838 ds0 = src->data[0];
839 ds1 = src->data[1];
840 ds2 = src->data[2];
841
842 for (y=0; y<r->h; y+=2) {
843
844 yd = y + r->y;
845
846 ys = (unsigned)(y * rh);
847 ys2 = (unsigned)((y+1) * rh);
848
849 lineh(r->x, r->w, rw, yd, ys, ys2,
850 dd0, dd1, dd2, lsd,
851 ds0, ds1, ds2, lss);
852 }
853 }
854
855
856 /**
857 * Same as vidconv(), but maintain source aspect ratio within bounds of r
858 *
859 * @param dst Destination video frame
860 * @param src Source video frame
861 * @param r Drawing area in destination frame
862 */
vidconv_aspect(struct vidframe * dst,const struct vidframe * src,struct vidrect * r)863 void vidconv_aspect(struct vidframe *dst, const struct vidframe *src,
864 struct vidrect *r)
865 {
866 struct vidsz asz;
867 double ar;
868
869 ar = (double)src->size.w / (double)src->size.h;
870
871 asz.w = r->w;
872 asz.h = r->h;
873
874 r->w = (unsigned)min((double)asz.w, (double)asz.h * ar);
875 r->h = (unsigned)min((double)asz.h, (double)asz.w / ar);
876 r->x = r->x + (asz.w - r->w) / 2;
877 r->y = r->y + (asz.h - r->h) / 2;
878
879 vidconv(dst, src, r);
880 }
881