1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #include <config.h>
26
27 #include <gavl/gavl.h>
28 #include "colormatrix.h"
29 #include <gmerlin/translation.h>
30
31 #include <gmerlin/log.h>
32 #define LOG_DOMAIN "colormatrix"
33
34 #define CLAMP_FLOAT(val) (val > 1.0) ? 1.0 : ((val < 0.0) ? 0.0 : val)
35 #define CLAMP_FLOAT_UV(val) (val > 0.5) ? 0.5 : ((val < -0.5) ? -0.5 : val)
36
37 typedef struct
38 {
39 float coeffs_f[4][5];
40 int coeffs_i[4][5];
41 } matrix_t;
42
43 #if 0
44 static void dump_matrix(float coeffs_f[4][5])
45 {
46 int i;
47 fprintf(stderr, "Matrix\n");
48 for(i = 0; i < 4; i++)
49 {
50 fprintf(stderr, "%f %f %f %f %f\n",
51 coeffs_f[i][0],
52 coeffs_f[i][1],
53 coeffs_f[i][2],
54 coeffs_f[i][3],
55 coeffs_f[i][4]);
56 }
57 }
58 #endif
59
60 struct bg_colormatrix_s
61 {
62 matrix_t rgba;
63 matrix_t yuva;
64
65 void (*func)(void * priv, int start, int end);
66 gavl_video_format_t format;
67
68 /* Multithreading stuff */
69
70 gavl_video_run_func run_func;
71 void * run_data;
72 gavl_video_stop_func stop_func;
73 void * stop_data;
74 int num_threads;
75
76 gavl_video_frame_t * frame;
77 };
78
matrixmult_cn(const float coeffs1[4][5],float coeffs2[4][5],float result[4][5])79 static void matrixmult_cn(const float coeffs1[4][5],
80 float coeffs2[4][5],
81 float result[4][5])
82 {
83 int i, j;
84
85 for(i = 0; i < 4; i++)
86 {
87 for(j = 0; j < 5; j++)
88 {
89 result[i][j] =
90 coeffs1[i][0] * coeffs2[0][j] +
91 coeffs1[i][1] * coeffs2[1][j] +
92 coeffs1[i][2] * coeffs2[2][j] +
93 coeffs1[i][3] * coeffs2[3][j];
94 }
95 result[i][4] += coeffs1[i][4];
96 }
97 }
98
matrixmult_nc(float coeffs1[4][5],const float coeffs2[4][5],float result[4][5])99 static void matrixmult_nc(float coeffs1[4][5],
100 const float coeffs2[4][5],
101 float result[4][5])
102 {
103 int i, j;
104
105 for(i = 0; i < 4; i++)
106 {
107 for(j = 0; j < 5; j++)
108 {
109 result[i][j] =
110 coeffs1[i][0] * coeffs2[0][j] +
111 coeffs1[i][1] * coeffs2[1][j] +
112 coeffs1[i][2] * coeffs2[2][j] +
113 coeffs1[i][3] * coeffs2[3][j];
114 }
115 result[i][4] += coeffs1[i][4];
116 }
117 }
118
119 static const float rgba_2_yuva[4][5] =
120 {
121 /* ry gy by ay oy */
122 { 0.299000, 0.587000, 0.114000, 0.0, 0.0 },
123 /* ru gu bu au ou */
124 { -0.168736, -0.331264, 0.500000, 0.0, 0.0 },
125 /* rv gv bv av ov */
126 { 0.500000, -0.418688, -0.081312, 0.0, 0.0 },
127 /* ra ga ba aa oa */
128 { 0.0, 0.0, 0.0, 1.0, 0.0 },
129 };
130
131
132 static const float yuva_2_rgba[4][5] =
133 {
134 /* yr ur vr ar or */
135 { 1.0, 0.000000, 1.402000, 0.0, 0.0 },
136 /* yg ug vg ag og */
137 { 1.0, -0.344136, -0.714136, 0.0, 0.0},
138 /* yb ub vb ab ob */
139 { 1.0, 1.772000, 0.000000, 0.0, 0.0},
140 /* ya ua va aa oa */
141 { 0.0, 0.000000, 0.000000, 1.0, 0.0 },
142 };
143
colormatrix_rgb2yuv(float coeffs_in[4][5],float coeffs_out[4][5])144 static void colormatrix_rgb2yuv(float coeffs_in[4][5],
145 float coeffs_out[4][5])
146 {
147 float coeffs_tmp[4][5];
148 matrixmult_cn(rgba_2_yuva, coeffs_in, coeffs_tmp);
149 matrixmult_nc(coeffs_tmp, yuva_2_rgba, coeffs_out);
150 }
151
colormatrix_yuv2rgb(float coeffs_in[4][5],float coeffs_out[4][5])152 static void colormatrix_yuv2rgb(float coeffs_in[4][5],
153 float coeffs_out[4][5])
154 {
155 float coeffs_tmp[4][5];
156 matrixmult_cn(yuva_2_rgba, coeffs_in, coeffs_tmp);
157 matrixmult_nc(coeffs_tmp, rgba_2_yuva, coeffs_out);
158 }
159
colormatrix_set_4(float coeffs_in[4][5],float coeffs_out[4][5])160 static void colormatrix_set_4(float coeffs_in[4][5],
161 float coeffs_out[4][5])
162 {
163 int i, j;
164 for(i = 0; i < 4; i++)
165 {
166 for(j = 0; j < 5; j++)
167 coeffs_out[i][j] = coeffs_in[i][j];
168 }
169 }
170
colormatrix_set_3(float coeffs_in[3][4],float coeffs_out[4][5])171 static void colormatrix_set_3(float coeffs_in[3][4],
172 float coeffs_out[4][5])
173 {
174 int i, j;
175 for(i = 0; i < 3; i++)
176 {
177 for(j = 0; j < 3; j++)
178 coeffs_out[i][j] = coeffs_in[i][j];
179
180 coeffs_out[i][3] = 0.0;
181 coeffs_out[i][4] = coeffs_in[i][3];
182 }
183 coeffs_out[3][0] = 0.0;
184 coeffs_out[3][1] = 0.0;
185 coeffs_out[3][2] = 0.0;
186 coeffs_out[3][3] = 1.0;
187 }
188
bg_colormatrix_create()189 bg_colormatrix_t * bg_colormatrix_create()
190 {
191 bg_colormatrix_t * ret;
192 ret = calloc(1, sizeof(*ret));
193
194 return ret;
195 }
196
bg_colormatrix_destroy(bg_colormatrix_t * m)197 void bg_colormatrix_destroy(bg_colormatrix_t * m)
198 {
199 free(m);
200 }
201
202 /* */
203
204 /* Gray */
205
process_gray_8(void * priv,int start,int end)206 static void process_gray_8(void * priv, int start, int end)
207 {
208 int g;
209 int i, j;
210 uint8_t * src;
211
212 bg_colormatrix_t * m = priv;
213 gavl_video_frame_t * in = m->frame;
214
215 for(i = start; i < end; i++)
216 {
217 src = in->planes[0] + i * in->strides[0];
218
219 for(j = 0; j < m->format.image_width; j++)
220 {
221 g =
222 ((m->yuva.coeffs_i[0][0] * src[0]) >> 8) +
223 m->yuva.coeffs_i[0][4];
224
225 src[0] = (uint8_t)((g & ~0xFF)?((-g) >> 31) : g);
226 src++;
227 }
228 }
229
230 }
231
232
process_graya_16(void * priv,int start,int end)233 static void process_graya_16(void * priv, int start, int end)
234 {
235 int g, a;
236 int i, j;
237 uint8_t * src;
238 bg_colormatrix_t * m = priv;
239 gavl_video_frame_t * in = m->frame;
240 for(i = start; i < end; i++)
241 {
242 src = in->planes[0] + i * in->strides[0];
243
244 for(j = 0; j < m->format.image_width; j++)
245 {
246 g =
247 ((m->yuva.coeffs_i[0][0] * (src[0]) +
248 m->yuva.coeffs_i[0][3] * src[1]) >> 8) +
249 m->yuva.coeffs_i[0][4];
250
251 a =
252 ((m->yuva.coeffs_i[3][0] * (src[0]) +
253 m->yuva.coeffs_i[3][3] * src[1]) >> 8) +
254 m->yuva.coeffs_i[3][4];
255
256 src[0] = (uint8_t)((g & ~0xFF)?((-g) >> 31) : g);
257 src[1] = (uint8_t)((a & ~0xFF)?((-a) >> 31) : a);
258
259 src += 2;
260 }
261 }
262
263 }
264
265 /* */
266
process_gray_16(void * priv,int start,int end)267 static void process_gray_16(void * priv, int start, int end)
268 {
269 int64_t g;
270 int i, j;
271 uint16_t * src;
272 bg_colormatrix_t * m = priv;
273 gavl_video_frame_t * in = m->frame;
274 for(i = start; i < end; i++)
275 {
276 src = (uint16_t*)(in->planes[0] + i * in->strides[0]);
277
278 for(j = 0; j < m->format.image_width; j++)
279 {
280 g =
281 (((int64_t)m->yuva.coeffs_i[0][0] * src[0]) >> 16) +
282 m->yuva.coeffs_i[0][4];
283
284 src[0] = (uint16_t)((g & ~0xFFFF)?((-g) >> 63) : g);
285 src++;
286 }
287 }
288
289 }
290
291
process_graya_32(void * priv,int start,int end)292 static void process_graya_32(void * priv, int start, int end)
293 {
294 int64_t g, a;
295 int i, j;
296 uint16_t * src;
297 bg_colormatrix_t * m = priv;
298 gavl_video_frame_t * in = m->frame;
299 for(i = start; i < end; i++)
300 {
301 src = (uint16_t*)(in->planes[0] + i * in->strides[0]);
302
303 for(j = 0; j < m->format.image_width; j++)
304 {
305 g =
306 (((int64_t)m->yuva.coeffs_i[0][0] * (src[0]) +
307 m->yuva.coeffs_i[0][3] * src[1]) >> 16) +
308 m->yuva.coeffs_i[0][4];
309
310 a =
311 (((int64_t)m->yuva.coeffs_i[3][0] * (src[0]) +
312 m->yuva.coeffs_i[3][3] * src[1]) >> 16) +
313 m->yuva.coeffs_i[3][4];
314
315 src[0] = (uint16_t)((g & ~0xFFFF)?((-g) >> 63) : g);
316 src[1] = (uint16_t)((a & ~0xFFFF)?((-a) >> 63) : a);
317
318 src += 2;
319 }
320 }
321
322 }
323
324
process_gray_float(void * priv,int start,int end)325 static void process_gray_float(void * priv, int start, int end)
326 {
327 float g;
328 int i, j;
329 float * src;
330 bg_colormatrix_t * m = priv;
331 gavl_video_frame_t * in = m->frame;
332 for(i = start; i < end; i++)
333 {
334 src = (float*)(in->planes[0] + i * in->strides[0]);
335
336 for(j = 0; j < m->format.image_width; j++)
337 {
338 g =
339 (m->yuva.coeffs_f[0][0] * src[0]) + m->yuva.coeffs_f[0][4];
340
341 src[0] = CLAMP_FLOAT(g);
342 src++;
343 }
344 }
345
346 }
347
348
process_graya_float(void * priv,int start,int end)349 static void process_graya_float(void * priv, int start, int end)
350 {
351 float g, a;
352 int i, j;
353 float * src;
354 bg_colormatrix_t * m = priv;
355 gavl_video_frame_t * in = m->frame;
356 for(i = start; i < end; i++)
357 {
358 src = (float*)(in->planes[0] + i * in->strides[0]);
359
360 for(j = 0; j < m->format.image_width; j++)
361 {
362 g =
363 ((m->yuva.coeffs_f[0][0] * (src[0]) +
364 m->yuva.coeffs_f[0][3] * src[1])) +
365 m->yuva.coeffs_f[0][4];
366
367 a =
368 ((m->yuva.coeffs_f[3][0] * (src[0]) +
369 m->yuva.coeffs_f[3][3] * src[1])) +
370 m->yuva.coeffs_f[3][4];
371
372 src[0] = CLAMP_FLOAT(g);
373 src[1] = CLAMP_FLOAT(a);
374
375 src += 2;
376 }
377 }
378
379 }
380
381
382
383
384
385 /* RGB(A) 8 bit */
386
387
process_bgr_24(void * priv,int start,int end)388 static void process_bgr_24(void * priv, int start, int end)
389 {
390 int i, j;
391 int r, g, b;
392 uint8_t * src;
393 bg_colormatrix_t * m = priv;
394 gavl_video_frame_t * in = m->frame;
395 for(i = start; i < end; i++)
396 {
397 src = in->planes[0] + i * in->strides[0];
398
399 for(j = 0; j < m->format.image_width; j++)
400 {
401 r =
402 ((m->rgba.coeffs_i[0][0] * src[2] +
403 m->rgba.coeffs_i[0][1] * src[1] +
404 m->rgba.coeffs_i[0][2] * src[0]) >> 8) +
405 m->rgba.coeffs_i[0][4];
406
407 g =
408 ((m->rgba.coeffs_i[1][0] * src[2] +
409 m->rgba.coeffs_i[1][1] * src[1] +
410 m->rgba.coeffs_i[1][2] * src[0]) >> 8) +
411 m->rgba.coeffs_i[1][4];
412
413 b =
414 ((m->rgba.coeffs_i[2][0] * src[2] +
415 m->rgba.coeffs_i[2][1] * src[1] +
416 m->rgba.coeffs_i[2][2] * src[0]) >> 8) +
417 m->rgba.coeffs_i[2][4];
418
419 src[2] = (uint8_t)((r & ~0xFF)?((-r) >> 31) : r);
420 src[1] = (uint8_t)((g & ~0xFF)?((-g) >> 31) : g);
421 src[0] = (uint8_t)((b & ~0xFF)?((-b) >> 31) : b);
422
423 src += 3;
424 }
425 }
426 }
427
process_rgb_24(void * priv,int start,int end)428 static void process_rgb_24(void * priv, int start, int end)
429 {
430 int i, j;
431 int r, g, b;
432 uint8_t * src;
433 bg_colormatrix_t * m = priv;
434 gavl_video_frame_t * in = m->frame;
435 for(i = start; i < end; i++)
436 {
437 src = in->planes[0] + i * in->strides[0];
438
439 for(j = 0; j < m->format.image_width; j++)
440 {
441 r =
442 ((m->rgba.coeffs_i[0][0] * src[0] +
443 m->rgba.coeffs_i[0][1] * src[1] +
444 m->rgba.coeffs_i[0][2] * src[2]) >> 8) +
445 m->rgba.coeffs_i[0][4];
446
447 g =
448 ((m->rgba.coeffs_i[1][0] * src[0] +
449 m->rgba.coeffs_i[1][1] * src[1] +
450 m->rgba.coeffs_i[1][2] * src[2]) >> 8) +
451 m->rgba.coeffs_i[1][4];
452
453 b =
454 ((m->rgba.coeffs_i[2][0] * src[0] +
455 m->rgba.coeffs_i[2][1] * src[1] +
456 m->rgba.coeffs_i[2][2] * src[2]) >> 8) +
457 m->rgba.coeffs_i[2][4];
458
459 src[0] = (uint8_t)((r & ~0xFF)?((-r) >> 31) : r);
460 src[1] = (uint8_t)((g & ~0xFF)?((-g) >> 31) : g);
461 src[2] = (uint8_t)((b & ~0xFF)?((-b) >> 31) : b);
462
463 src += 3;
464 }
465 }
466 }
467
468
process_bgr_32(void * priv,int start,int end)469 static void process_bgr_32(void * priv, int start, int end)
470 {
471 int i, j;
472 int r, g, b;
473 uint8_t * src;
474 bg_colormatrix_t * m = priv;
475 gavl_video_frame_t * in = m->frame;
476 for(i = start; i < end; i++)
477 {
478 src = in->planes[0] + i * in->strides[0];
479
480 for(j = 0; j < m->format.image_width; j++)
481 {
482 r =
483 ((m->rgba.coeffs_i[0][0] * src[2] +
484 m->rgba.coeffs_i[0][1] * src[1] +
485 m->rgba.coeffs_i[0][2] * src[0]) >> 8) +
486 m->rgba.coeffs_i[0][4];
487
488 g =
489 ((m->rgba.coeffs_i[1][0] * src[2] +
490 m->rgba.coeffs_i[1][1] * src[1] +
491 m->rgba.coeffs_i[1][2] * src[0]) >> 8) +
492 m->rgba.coeffs_i[1][4];
493
494 b =
495 ((m->rgba.coeffs_i[2][0] * src[2] +
496 m->rgba.coeffs_i[2][1] * src[1] +
497 m->rgba.coeffs_i[2][2] * src[0]) >> 8) +
498 m->rgba.coeffs_i[2][4];
499
500 src[2] = (uint8_t)((r & ~0xFF)?((-r) >> 31) : r);
501 src[1] = (uint8_t)((g & ~0xFF)?((-g) >> 31) : g);
502 src[0] = (uint8_t)((b & ~0xFF)?((-b) >> 31) : b);
503
504 src += 4;
505 }
506 }
507 }
508
process_rgb_32(void * priv,int start,int end)509 static void process_rgb_32(void * priv, int start, int end)
510 {
511 int i, j;
512 int r, g, b;
513 uint8_t * src;
514 bg_colormatrix_t * m = priv;
515 gavl_video_frame_t * in = m->frame;
516 for(i = start; i < end; i++)
517 {
518 src = in->planes[0] + i * in->strides[0];
519
520 for(j = 0; j < m->format.image_width; j++)
521 {
522 r =
523 ((m->rgba.coeffs_i[0][0] * src[0] +
524 m->rgba.coeffs_i[0][1] * src[1] +
525 m->rgba.coeffs_i[0][2] * src[2]) >> 8) +
526 m->rgba.coeffs_i[0][4];
527
528 g =
529 ((m->rgba.coeffs_i[1][0] * src[0] +
530 m->rgba.coeffs_i[1][1] * src[1] +
531 m->rgba.coeffs_i[1][2] * src[2]) >> 8) +
532 m->rgba.coeffs_i[1][4];
533
534 b =
535 ((m->rgba.coeffs_i[2][0] * src[0] +
536 m->rgba.coeffs_i[2][1] * src[1] +
537 m->rgba.coeffs_i[2][2] * src[2]) >> 8) +
538 m->rgba.coeffs_i[2][4];
539
540 src[0] = (uint8_t)((r & ~0xFF)?((-r) >> 31) : r);
541 src[1] = (uint8_t)((g & ~0xFF)?((-g) >> 31) : g);
542 src[2] = (uint8_t)((b & ~0xFF)?((-b) >> 31) : b);
543
544 src += 4;
545 }
546 }
547 }
548
process_rgba_32(void * priv,int start,int end)549 static void process_rgba_32(void * priv, int start, int end)
550 {
551 int i, j;
552 uint8_t * src;
553 int r, g, b, a;
554 bg_colormatrix_t * m = priv;
555 gavl_video_frame_t * in = m->frame;
556
557 for(i = start; i < end; i++)
558 {
559 src = in->planes[0] + i * in->strides[0];
560
561 for(j = 0; j < m->format.image_width; j++)
562 {
563 r =
564 ((m->rgba.coeffs_i[0][0] * src[0] +
565 m->rgba.coeffs_i[0][1] * src[1] +
566 m->rgba.coeffs_i[0][2] * src[2] +
567 m->rgba.coeffs_i[0][3] * src[3]) >> 8) +
568 m->rgba.coeffs_i[0][4];
569
570 g =
571 ((m->rgba.coeffs_i[1][0] * src[0] +
572 m->rgba.coeffs_i[1][1] * src[1] +
573 m->rgba.coeffs_i[1][2] * src[2] +
574 m->rgba.coeffs_i[1][3] * src[3]) >> 8) +
575 m->rgba.coeffs_i[1][4];
576
577 b =
578 ((m->rgba.coeffs_i[2][0] * src[0] +
579 m->rgba.coeffs_i[2][1] * src[1] +
580 m->rgba.coeffs_i[2][2] * src[2] +
581 m->rgba.coeffs_i[2][3] * src[3]) >> 8) +
582 m->rgba.coeffs_i[2][4];
583
584 a =
585 ((m->rgba.coeffs_i[3][0] * src[0] +
586 m->rgba.coeffs_i[3][1] * src[1] +
587 m->rgba.coeffs_i[3][2] * src[2] +
588 m->rgba.coeffs_i[3][3] * src[3]) >> 8) +
589 m->rgba.coeffs_i[3][4];
590
591 src[0] = (uint8_t)((r & ~0xFF)?((-r) >> 31) : r);
592 src[1] = (uint8_t)((g & ~0xFF)?((-g) >> 31) : g);
593 src[2] = (uint8_t)((b & ~0xFF)?((-b) >> 31) : b);
594 src[3] = (uint8_t)((a & ~0xFF)?((-a) >> 31) : a);
595
596 src += 4;
597 }
598 }
599
600 }
601
602 /* RGB(A) 16 bit */
603
process_rgb_48(void * priv,int start,int end)604 static void process_rgb_48(void * priv, int start, int end)
605 {
606 int64_t r, g, b;
607 int i, j;
608 uint16_t * src;
609 bg_colormatrix_t * m = priv;
610 gavl_video_frame_t * in = m->frame;
611
612 for(i = start; i < end; i++)
613 {
614 src = (uint16_t *)(in->planes[0] + i * in->strides[0]);
615
616 for(j = 0; j < m->format.image_width; j++)
617 {
618 r =
619 (((int64_t)m->rgba.coeffs_i[0][0] * (int64_t)src[0] +
620 (int64_t)m->rgba.coeffs_i[0][1] * (int64_t)src[1] +
621 (int64_t)m->rgba.coeffs_i[0][2] * (int64_t)src[2]) >> 16) +
622 (int64_t)m->rgba.coeffs_i[0][4];
623
624 g =
625 (((int64_t)m->rgba.coeffs_i[1][0] * (int64_t)src[0] +
626 (int64_t)m->rgba.coeffs_i[1][1] * (int64_t)src[1] +
627 (int64_t)m->rgba.coeffs_i[1][2] * (int64_t)src[2]) >> 16) +
628 (int64_t)m->rgba.coeffs_i[1][4];
629
630 b =
631 (((int64_t)m->rgba.coeffs_i[2][0] * (int64_t)src[0] +
632 (int64_t)m->rgba.coeffs_i[2][1] * (int64_t)src[1] +
633 (int64_t)m->rgba.coeffs_i[2][2] * (int64_t)src[2]) >> 16) +
634 (int64_t)m->rgba.coeffs_i[2][4];
635
636 src[0] = (uint16_t)((r & ~0xFFFF)?((-r) >> 63) : r);
637 src[1] = (uint16_t)((g & ~0xFFFF)?((-g) >> 63) : g);
638 src[2] = (uint16_t)((b & ~0xFFFF)?((-b) >> 63) : b);
639
640 src += 3;
641 }
642 }
643 }
644
process_rgba_64(void * priv,int start,int end)645 static void process_rgba_64(void * priv, int start, int end)
646 {
647 int64_t r, g, b, a;
648 int i, j;
649 uint16_t * src;
650 bg_colormatrix_t * m = priv;
651 gavl_video_frame_t * in = m->frame;
652
653 for(i = start; i < end; i++)
654 {
655 src = (uint16_t *)(in->planes[0] + i * in->strides[0]);
656
657 for(j = 0; j < m->format.image_width; j++)
658 {
659 r =
660 (((int64_t)m->rgba.coeffs_i[0][0] * (int64_t)src[0] +
661 (int64_t)m->rgba.coeffs_i[0][1] * (int64_t)src[1] +
662 (int64_t)m->rgba.coeffs_i[0][2] * (int64_t)src[2] +
663 (int64_t)m->rgba.coeffs_i[0][3] * (int64_t)src[3]) >> 16) +
664 (int64_t)m->rgba.coeffs_i[0][4];
665
666 g =
667 (((int64_t)m->rgba.coeffs_i[1][0] * (int64_t)src[0] +
668 (int64_t)m->rgba.coeffs_i[1][1] * (int64_t)src[1] +
669 (int64_t)m->rgba.coeffs_i[1][2] * (int64_t)src[2] +
670 (int64_t)m->rgba.coeffs_i[1][3] * (int64_t)src[3]) >> 16) +
671 (int64_t)m->rgba.coeffs_i[1][4];
672
673 b =
674 (((int64_t)m->rgba.coeffs_i[2][0] * (int64_t)src[0] +
675 (int64_t)m->rgba.coeffs_i[2][1] * (int64_t)src[1] +
676 (int64_t)m->rgba.coeffs_i[2][2] * (int64_t)src[2] +
677 (int64_t)m->rgba.coeffs_i[2][3] * (int64_t)src[3]) >> 16) +
678 (int64_t)m->rgba.coeffs_i[2][4];
679
680 a =
681 (((int64_t)m->rgba.coeffs_i[3][0] * (int64_t)src[0] +
682 (int64_t)m->rgba.coeffs_i[3][1] * (int64_t)src[1] +
683 (int64_t)m->rgba.coeffs_i[3][2] * (int64_t)src[2] +
684 (int64_t)m->rgba.coeffs_i[3][3] * (int64_t)src[3]) >> 16) +
685 (int64_t)m->rgba.coeffs_i[3][4];
686
687 src[0] = (uint16_t)((r & ~0xFFFF)?((-r) >> 63) : r);
688 src[1] = (uint16_t)((g & ~0xFFFF)?((-g) >> 63) : g);
689 src[2] = (uint16_t)((b & ~0xFFff)?((-b) >> 63) : b);
690 src[3] = (uint16_t)((a & ~0xFFFF)?((-a) >> 63) : a);
691
692 src += 4;
693 }
694 }
695
696 }
697
698
699 /* Float */
700
process_rgb_float(void * priv,int start,int end)701 static void process_rgb_float(void * priv, int start, int end)
702 {
703 int i, j;
704 float * src;
705 float r, g, b;
706 bg_colormatrix_t * m = priv;
707 gavl_video_frame_t * in = m->frame;
708
709 for(i = start; i < end; i++)
710 {
711 src = (float *)(in->planes[0] + i * in->strides[0]);
712
713 for(j = 0; j < m->format.image_width; j++)
714 {
715 r =
716 m->rgba.coeffs_f[0][0] * src[0] +
717 m->rgba.coeffs_f[0][1] * src[1] +
718 m->rgba.coeffs_f[0][2] * src[2] +
719 m->rgba.coeffs_f[0][4];
720 g =
721 m->rgba.coeffs_f[1][0] * src[0] +
722 m->rgba.coeffs_f[1][1] * src[1] +
723 m->rgba.coeffs_f[1][2] * src[2] +
724 m->rgba.coeffs_f[1][4];
725 b =
726 m->rgba.coeffs_f[2][0] * src[0] +
727 m->rgba.coeffs_f[2][1] * src[1] +
728 m->rgba.coeffs_f[2][2] * src[2] +
729 m->rgba.coeffs_f[2][4];
730 src[0] = CLAMP_FLOAT(r);
731 src[1] = CLAMP_FLOAT(g);
732 src[2] = CLAMP_FLOAT(b);
733 src += 3;
734 }
735 }
736 }
737
738
process_rgba_float(void * priv,int start,int end)739 static void process_rgba_float(void * priv, int start, int end)
740 {
741 int i, j;
742 float * src;
743 float r, g, b, a;
744
745 bg_colormatrix_t * m = priv;
746 gavl_video_frame_t * in = m->frame;
747
748 for(i = start; i < end; i++)
749 {
750 src = (float *)(in->planes[0] + i * in->strides[0]);
751
752 for(j = 0; j < m->format.image_width; j++)
753 {
754 r =
755 m->rgba.coeffs_f[0][0] * src[0] +
756 m->rgba.coeffs_f[0][1] * src[1] +
757 m->rgba.coeffs_f[0][2] * src[2] +
758 m->rgba.coeffs_f[0][3] * src[3] +
759 m->rgba.coeffs_f[0][4];
760 g =
761 m->rgba.coeffs_f[1][0] * src[0] +
762 m->rgba.coeffs_f[1][1] * src[1] +
763 m->rgba.coeffs_f[1][2] * src[2] +
764 m->rgba.coeffs_f[1][3] * src[3] +
765 m->rgba.coeffs_f[1][4];
766 b =
767 m->rgba.coeffs_f[2][0] * src[0] +
768 m->rgba.coeffs_f[2][1] * src[1] +
769 m->rgba.coeffs_f[2][2] * src[2] +
770 m->rgba.coeffs_f[2][3] * src[3] +
771 m->rgba.coeffs_f[2][4];
772 a =
773 m->rgba.coeffs_f[3][0] * src[0] +
774 m->rgba.coeffs_f[3][1] * src[1] +
775 m->rgba.coeffs_f[3][2] * src[2] +
776 m->rgba.coeffs_f[3][3] * src[3] +
777 m->rgba.coeffs_f[3][4];
778 src[0] = CLAMP_FLOAT(r);
779 src[1] = CLAMP_FLOAT(g);
780 src[2] = CLAMP_FLOAT(b);
781 src[3] = CLAMP_FLOAT(a);
782
783 src += 4;
784 }
785 }
786 }
787
process_yuv_float(void * priv,int start,int end)788 static void process_yuv_float(void * priv, int start, int end)
789 {
790 int i, j;
791 float * src;
792 float y, u, v;
793 bg_colormatrix_t * m = priv;
794 gavl_video_frame_t * in = m->frame;
795 for(i = start; i < end; i++)
796 {
797 src = (float *)(in->planes[0] + i * in->strides[0]);
798
799 for(j = 0; j < m->format.image_width; j++)
800 {
801 y =
802 m->yuva.coeffs_f[0][0] * src[0] +
803 m->yuva.coeffs_f[0][1] * src[1] +
804 m->yuva.coeffs_f[0][2] * src[2] +
805 m->yuva.coeffs_f[0][4];
806 u =
807 m->yuva.coeffs_f[1][0] * src[0] +
808 m->yuva.coeffs_f[1][1] * src[1] +
809 m->yuva.coeffs_f[1][2] * src[2] +
810 m->yuva.coeffs_f[1][4];
811 v =
812 m->yuva.coeffs_f[2][0] * src[0] +
813 m->yuva.coeffs_f[2][1] * src[1] +
814 m->yuva.coeffs_f[2][2] * src[2] +
815 m->yuva.coeffs_f[2][4];
816 src[0] = CLAMP_FLOAT(y);
817 src[1] = CLAMP_FLOAT_UV(u);
818 src[2] = CLAMP_FLOAT_UV(v);
819 src += 3;
820 }
821 }
822 }
823
824
process_yuva_float(void * priv,int start,int end)825 static void process_yuva_float(void * priv, int start, int end)
826 {
827 int i, j;
828 float * src;
829 float y, u, v, a;
830 bg_colormatrix_t * m = priv;
831 gavl_video_frame_t * in = m->frame;
832 for(i = start; i < end; i++)
833 {
834 src = (float *)(in->planes[0] + i * in->strides[0]);
835
836 for(j = 0; j < m->format.image_width; j++)
837 {
838 y =
839 m->yuva.coeffs_f[0][0] * src[0] +
840 m->yuva.coeffs_f[0][1] * src[1] +
841 m->yuva.coeffs_f[0][2] * src[2] +
842 m->yuva.coeffs_f[0][3] * src[3] +
843 m->yuva.coeffs_f[0][4];
844 u =
845 m->yuva.coeffs_f[1][0] * src[0] +
846 m->yuva.coeffs_f[1][1] * src[1] +
847 m->yuva.coeffs_f[1][2] * src[2] +
848 m->yuva.coeffs_f[1][3] * src[3] +
849 m->yuva.coeffs_f[1][4];
850 v =
851 m->yuva.coeffs_f[2][0] * src[0] +
852 m->yuva.coeffs_f[2][1] * src[1] +
853 m->yuva.coeffs_f[2][2] * src[2] +
854 m->yuva.coeffs_f[2][3] * src[3] +
855 m->yuva.coeffs_f[2][4];
856 a =
857 m->yuva.coeffs_f[3][0] * src[0] +
858 m->yuva.coeffs_f[3][1] * src[1] +
859 m->yuva.coeffs_f[3][2] * src[2] +
860 m->yuva.coeffs_f[3][3] * src[3] +
861 m->yuva.coeffs_f[3][4];
862 src[0] = CLAMP_FLOAT(y);
863 src[1] = CLAMP_FLOAT_UV(u);
864 src[2] = CLAMP_FLOAT_UV(v);
865 src[3] = CLAMP_FLOAT(a);
866
867 src += 4;
868 }
869 }
870 }
871
process_yuva_32(void * priv,int start,int end)872 static void process_yuva_32(void * priv, int start, int end)
873 {
874 int y, u, v, a;
875 int i, j;
876 uint8_t * src;
877 bg_colormatrix_t * m = priv;
878 gavl_video_frame_t * in = m->frame;
879 for(i = start; i < end; i++)
880 {
881 src = in->planes[0] + i * in->strides[0];
882
883 for(j = 0; j < m->format.image_width; j++)
884 {
885 y =
886 ((m->yuva.coeffs_i[0][0] * (src[0] - 0x10) +
887 m->yuva.coeffs_i[0][1] * (src[1] - 0x80) +
888 m->yuva.coeffs_i[0][2] * (src[2] - 0x80) +
889 m->yuva.coeffs_i[0][3] * src[3]) >> 8) +
890 m->yuva.coeffs_i[0][4];
891 y += 0x10;
892
893 u =
894 ((m->yuva.coeffs_i[1][0] * (src[0] - 0x10) +
895 m->yuva.coeffs_i[1][1] * (src[1] - 0x80) +
896 m->yuva.coeffs_i[1][2] * (src[2] - 0x80) +
897 m->yuva.coeffs_i[1][3] * src[3]) >> 8) +
898 m->yuva.coeffs_i[1][4];
899 u += 0x80;
900
901 v =
902 ((m->yuva.coeffs_i[2][0] * (src[0] - 0x10) +
903 m->yuva.coeffs_i[2][1] * (src[1] - 0x80) +
904 m->yuva.coeffs_i[2][2] * (src[2] - 0x80) +
905 m->yuva.coeffs_i[2][3] * src[3]) >> 8) +
906 m->yuva.coeffs_i[2][4];
907 v += 0x80;
908
909 a =
910 ((m->yuva.coeffs_i[3][0] * (src[0] - 0x10) +
911 m->yuva.coeffs_i[3][1] * (src[1] - 0x80) +
912 m->yuva.coeffs_i[3][2] * (src[2] - 0x80) +
913 m->yuva.coeffs_i[3][3] * src[3]) >> 8) +
914 m->yuva.coeffs_i[3][4];
915
916 src[0] = (uint8_t)((y & ~0xFF)?((-y) >> 31) : y);
917 src[1] = (uint8_t)((u & ~0xFF)?((-u) >> 31) : u);
918 src[2] = (uint8_t)((v & ~0xFF)?((-v) >> 31) : v);
919 src[3] = (uint8_t)((a & ~0xFF)?((-a) >> 31) : a);
920
921 src += 4;
922 }
923 }
924
925 }
926
process_yuva_64(void * priv,int start,int end)927 static void process_yuva_64(void * priv, int start, int end)
928 {
929 int64_t y, u, v, a;
930 int i, j;
931 uint16_t * src;
932 bg_colormatrix_t * m = priv;
933 gavl_video_frame_t * in = m->frame;
934 for(i = start; i < end; i++)
935 {
936 src = (uint16_t*)(in->planes[0] + i * in->strides[0]);
937
938 for(j = 0; j < m->format.image_width; j++)
939 {
940 y =
941 (((int64_t)m->yuva.coeffs_i[0][0] * (src[0] - 0x1000) +
942 m->yuva.coeffs_i[0][1] * (src[1] - 0x8000) +
943 m->yuva.coeffs_i[0][2] * (src[2] - 0x8000) +
944 m->yuva.coeffs_i[0][3] * src[3]) >> 16) +
945 m->yuva.coeffs_i[0][4];
946 y += 0x1000;
947
948 u =
949 (((int64_t)m->yuva.coeffs_i[1][0] * (src[0] - 0x1000) +
950 m->yuva.coeffs_i[1][1] * (src[1] - 0x8000) +
951 m->yuva.coeffs_i[1][2] * (src[2] - 0x8000) +
952 m->yuva.coeffs_i[1][3] * src[3]) >> 16) +
953 m->yuva.coeffs_i[1][4];
954 u += 0x8000;
955
956 v =
957 (((int64_t)m->yuva.coeffs_i[2][0] * (src[0] - 0x1000) +
958 m->yuva.coeffs_i[2][1] * (src[1] - 0x8000) +
959 m->yuva.coeffs_i[2][2] * (src[2] - 0x8000) +
960 m->yuva.coeffs_i[2][3] * src[3]) >> 16) +
961 m->yuva.coeffs_i[2][4];
962 v += 0x8000;
963
964 a =
965 (((int64_t)m->yuva.coeffs_i[3][0] * (src[0] - 0x1000) +
966 m->yuva.coeffs_i[3][1] * (src[1] - 0x8000) +
967 m->yuva.coeffs_i[3][2] * (src[2] - 0x8000) +
968 m->yuva.coeffs_i[3][3] * src[3]) >> 16) +
969 m->yuva.coeffs_i[3][4];
970
971 src[0] = (uint16_t)((y & ~0xFFFF)?((-y) >> 63) : y);
972 src[1] = (uint16_t)((u & ~0xFFFF)?((-u) >> 63) : u);
973 src[2] = (uint16_t)((v & ~0xFFFF)?((-v) >> 63) : v);
974 src[3] = (uint16_t)((a & ~0xFFFF)?((-a) >> 63) : a);
975
976 src += 4;
977 }
978 }
979
980 }
981
982
983
process_444j(void * priv,int start,int end)984 static void process_444j(void * priv, int start, int end)
985 {
986 int y, u, v;
987 int i, j;
988 uint8_t * src_y, * src_u, *src_v;
989 bg_colormatrix_t * m = priv;
990 gavl_video_frame_t * in = m->frame;
991
992 for(i = start; i < end; i++)
993 {
994 src_y = in->planes[0] + i * in->strides[0];
995 src_u = in->planes[1] + i * in->strides[1];
996 src_v = in->planes[2] + i * in->strides[2];
997
998
999 for(j = 0; j < m->format.image_width; j++)
1000 {
1001 y =
1002 ((m->yuva.coeffs_i[0][0] * *src_y +
1003 m->yuva.coeffs_i[0][1] * (*src_u-0x80) +
1004 m->yuva.coeffs_i[0][2] * (*src_v-0x80)) >> 8) +
1005 m->yuva.coeffs_i[0][4];
1006
1007 u =
1008 ((m->yuva.coeffs_i[1][0] * *src_y +
1009 m->yuva.coeffs_i[1][1] * (*src_u-0x80) +
1010 m->yuva.coeffs_i[1][2] * (*src_v-0x80)) >> 8) +
1011 m->yuva.coeffs_i[1][4];
1012 u += 0x80;
1013
1014 v =
1015 ((m->yuva.coeffs_i[2][0] * *src_y +
1016 m->yuva.coeffs_i[2][1] * (*src_u-0x80) +
1017 m->yuva.coeffs_i[2][2] * (*src_v-0x80)) >> 8) +
1018 m->yuva.coeffs_i[2][4];
1019 v += 0x80;
1020
1021 *src_y = (uint8_t)((y & ~0xFF)?((-y) >> 31) : y);
1022 *src_u = (uint8_t)((u & ~0xFF)?((-u) >> 31) : u);
1023 *src_v = (uint8_t)((v & ~0xFF)?((-v) >> 31) : v);
1024
1025 src_y++;
1026 src_u++;
1027 src_v++;
1028
1029 }
1030 }
1031 }
1032
process_444(void * priv,int start,int end)1033 static void process_444(void * priv, int start, int end)
1034 {
1035 int y, u, v;
1036 int i, j;
1037 uint8_t * src_y, * src_u, *src_v;
1038 bg_colormatrix_t * m = priv;
1039 gavl_video_frame_t * in = m->frame;
1040
1041 for(i = start; i < end; i++)
1042 {
1043 src_y = in->planes[0] + i * in->strides[0];
1044 src_u = in->planes[1] + i * in->strides[1];
1045 src_v = in->planes[2] + i * in->strides[2];
1046
1047 for(j = 0; j < m->format.image_width; j++)
1048 {
1049 y =
1050 ((m->yuva.coeffs_i[0][0] * (*src_y-0x10) +
1051 m->yuva.coeffs_i[0][1] * (*src_u-0x80) +
1052 m->yuva.coeffs_i[0][2] * (*src_v-0x80)) >> 8) +
1053 m->yuva.coeffs_i[0][4];
1054 y += 0x10;
1055
1056 u =
1057 ((m->yuva.coeffs_i[1][0] * (*src_y-0x10) +
1058 m->yuva.coeffs_i[1][1] * (*src_u-0x80) +
1059 m->yuva.coeffs_i[1][2] * (*src_v-0x80)) >> 8) +
1060 m->yuva.coeffs_i[1][4];
1061 u += 0x80;
1062
1063 v =
1064 ((m->yuva.coeffs_i[2][0] * (*src_y-0x10) +
1065 m->yuva.coeffs_i[2][1] * (*src_u-0x80) +
1066 m->yuva.coeffs_i[2][2] * (*src_v-0x80)) >> 8) +
1067 m->yuva.coeffs_i[2][4];
1068 v += 0x80;
1069
1070 *src_y = (uint8_t)((y & ~0xFF)?((-y) >> 31) : y);
1071 *src_u = (uint8_t)((u & ~0xFF)?((-u) >> 31) : u);
1072 *src_v = (uint8_t)((v & ~0xFF)?((-v) >> 31) : v);
1073
1074 src_y++;
1075 src_u++;
1076 src_v++;
1077
1078 }
1079 }
1080 }
1081
process_444_16(void * priv,int start,int end)1082 static void process_444_16(void * priv, int start, int end)
1083 {
1084 int64_t y, u, v;
1085 int i, j;
1086 uint16_t * src_y, * src_u, *src_v;
1087 bg_colormatrix_t * m = priv;
1088 gavl_video_frame_t * in = m->frame;
1089
1090 for(i = start; i < end; i++)
1091 {
1092 src_y = (uint16_t*)(in->planes[0] + i * in->strides[0]);
1093 src_u = (uint16_t*)(in->planes[1] + i * in->strides[1]);
1094 src_v = (uint16_t*)(in->planes[2] + i * in->strides[2]);
1095
1096 for(j = 0; j < m->format.image_width; j++)
1097 {
1098 y =
1099 (((int64_t)m->yuva.coeffs_i[0][0] * (*src_y-0x1000) +
1100 m->yuva.coeffs_i[0][1] * (*src_u-0x8000) +
1101 m->yuva.coeffs_i[0][2] * (*src_v-0x8000)) >> 16) +
1102 m->yuva.coeffs_i[0][4];
1103 y += 0x1000;
1104
1105
1106 u =
1107 (((int64_t)m->yuva.coeffs_i[1][0] * (*src_y-0x1000) +
1108 m->yuva.coeffs_i[1][1] * (*src_u-0x8000) +
1109 m->yuva.coeffs_i[1][2] * (*src_v-0x8000)) >> 16) +
1110 m->yuva.coeffs_i[1][4];
1111 u += 0x8000;
1112
1113
1114 v =
1115 (((int64_t)m->yuva.coeffs_i[2][0] * (*src_y-0x1000) +
1116 m->yuva.coeffs_i[2][1] * (*src_u-0x8000) +
1117 m->yuva.coeffs_i[2][2] * (*src_v-0x8000)) >> 16) +
1118 m->yuva.coeffs_i[2][4];
1119 v += 0x8000;
1120
1121 *src_y = (uint16_t)((y & ~0xFFFF)?((-y) >> 63) : y);
1122 *src_u = (uint16_t)((u & ~0xFFFF)?((-u) >> 63) : u);
1123 *src_v = (uint16_t)((v & ~0xFFFF)?((-v) >> 63) : v);
1124
1125 src_y++;
1126 src_u++;
1127 src_v++;
1128 }
1129 }
1130 }
1131
1132
1133
matrix_f_to_8(matrix_t * mat)1134 static void matrix_f_to_8(matrix_t * mat)
1135 {
1136 int i, j;
1137 for(i = 0; i < 4; i++)
1138 {
1139 for(j = 0; j < 5; j++)
1140 mat->coeffs_i[i][j] = (int)(mat->coeffs_f[i][j] * 256.0 + 0.5);
1141 }
1142 }
1143
matrix_f_to_16(matrix_t * mat)1144 static void matrix_f_to_16(matrix_t * mat)
1145 {
1146 int i, j;
1147 for(i = 0; i < 4; i++)
1148 {
1149 for(j = 0; j < 5; j++)
1150 mat->coeffs_i[i][j] = (int)(mat->coeffs_f[i][j] * 65536.0 + 0.5);
1151 }
1152 }
1153
1154 #define SCALE_Y 219.0
1155 #define SCALE_UV 224.0
1156 #define SCALE_A 255.0
1157 #define SCALE_OFF 255.0
1158
matrix_f_to_8_yuv(matrix_t * mat)1159 static void matrix_f_to_8_yuv(matrix_t * mat)
1160 {
1161
1162 /* y -> y */
1163 mat->coeffs_i[0][0] = (int)(mat->coeffs_f[0][0] * 256.0 + 0.5);
1164 /* u -> y */
1165 mat->coeffs_i[0][1] = (int)(mat->coeffs_f[0][1] * 256.0 * SCALE_Y / SCALE_UV + 0.5);
1166 /* v -> y */
1167 mat->coeffs_i[0][2] = (int)(mat->coeffs_f[0][2] * 256.0 * SCALE_Y / SCALE_UV + 0.5);
1168 /* a -> y */
1169 mat->coeffs_i[0][3] = (int)(mat->coeffs_f[0][3] * 256.0 * SCALE_Y / SCALE_A + 0.5);
1170 /* y off */
1171 mat->coeffs_i[0][4] = (int)(mat->coeffs_f[0][4] * 256.0 * SCALE_Y / SCALE_OFF + 0.5);
1172
1173 /* y -> u */
1174 mat->coeffs_i[1][0] = (int)(mat->coeffs_f[1][0] * 256.0 * SCALE_UV / SCALE_Y + 0.5);
1175 /* u -> u */
1176 mat->coeffs_i[1][1] = (int)(mat->coeffs_f[1][1] * 256.0 + 0.5);
1177 /* v -> u */
1178 mat->coeffs_i[1][2] = (int)(mat->coeffs_f[1][2] * 256.0 + 0.5);
1179 /* a -> u */
1180 mat->coeffs_i[1][3] = (int)(mat->coeffs_f[1][3] * 256.0 * SCALE_UV / SCALE_A + 0.5);
1181 /* u off */
1182 mat->coeffs_i[1][4] = (int)(mat->coeffs_f[1][4] * 256.0 * SCALE_UV / SCALE_OFF + 0.5);
1183
1184 /* y -> v */
1185 mat->coeffs_i[2][0] = (int)(mat->coeffs_f[2][0] * 256.0 * SCALE_UV / SCALE_Y + 0.5);
1186 /* u -> v */
1187 mat->coeffs_i[2][1] = (int)(mat->coeffs_f[2][1] * 256.0 + 0.5);
1188 /* v -> v */
1189 mat->coeffs_i[2][2] = (int)(mat->coeffs_f[2][2] * 256.0 + 0.5);
1190 /* a -> v */
1191 mat->coeffs_i[2][3] = (int)(mat->coeffs_f[2][3] * 256.0 * SCALE_UV / SCALE_A + 0.5);
1192 /* v off */
1193 mat->coeffs_i[2][4] = (int)(mat->coeffs_f[2][4] * 256.0 * SCALE_UV / SCALE_OFF + 0.5);
1194
1195 /* y -> a */
1196 mat->coeffs_i[3][0] = (int)(mat->coeffs_f[3][0] * 256.0 * SCALE_A / SCALE_Y + 0.5);
1197 /* u -> a */
1198 mat->coeffs_i[3][1] = (int)(mat->coeffs_f[3][1] * 256.0 * SCALE_A / SCALE_UV + 0.5);
1199 /* v -> a */
1200 mat->coeffs_i[3][2] = (int)(mat->coeffs_f[3][2] * 256.0 * SCALE_A / SCALE_UV + 0.5);
1201 /* a -> a */
1202 mat->coeffs_i[3][3] = (int)(mat->coeffs_f[3][3] * 256.0 + 0.5);
1203 /* a off */
1204 mat->coeffs_i[3][4] = (int)(mat->coeffs_f[3][4] * 256.0 * SCALE_A / SCALE_OFF + 0.5);
1205 }
1206
matrix_f_to_16_yuv(matrix_t * mat)1207 static void matrix_f_to_16_yuv(matrix_t * mat)
1208 {
1209
1210 /* y -> y */
1211 mat->coeffs_i[0][0] = (int)(mat->coeffs_f[0][0] * 65536.0 + 0.5);
1212 /* u -> y */
1213 mat->coeffs_i[0][1] = (int)(mat->coeffs_f[0][1] * 65536.0 * SCALE_Y / SCALE_UV + 0.5);
1214 /* v -> y */
1215 mat->coeffs_i[0][2] = (int)(mat->coeffs_f[0][2] * 65536.0 * SCALE_Y / SCALE_UV + 0.5);
1216 /* a -> y */
1217 mat->coeffs_i[0][3] = (int)(mat->coeffs_f[0][3] * 65536.0 * SCALE_Y / SCALE_A + 0.5);
1218 /* y off */
1219 mat->coeffs_i[0][4] = (int)(mat->coeffs_f[0][4] * 65536.0 * SCALE_Y / SCALE_OFF + 0.5);
1220
1221 /* y -> u */
1222 mat->coeffs_i[1][0] = (int)(mat->coeffs_f[1][0] * 65536.0 * SCALE_UV / SCALE_Y + 0.5);
1223 /* u -> u */
1224 mat->coeffs_i[1][1] = (int)(mat->coeffs_f[1][1] * 65536.0 + 0.5);
1225 /* v -> u */
1226 mat->coeffs_i[1][2] = (int)(mat->coeffs_f[1][2] * 65536.0 + 0.5);
1227 /* a -> u */
1228 mat->coeffs_i[1][3] = (int)(mat->coeffs_f[1][3] * 65536.0 * SCALE_UV / SCALE_A + 0.5);
1229 /* u off */
1230 mat->coeffs_i[1][4] = (int)(mat->coeffs_f[1][4] * 65536.0 * SCALE_UV / SCALE_OFF + 0.5);
1231
1232 /* y -> v */
1233 mat->coeffs_i[2][0] = (int)(mat->coeffs_f[2][0] * 65536.0 * SCALE_UV / SCALE_Y + 0.5);
1234 /* u -> v */
1235 mat->coeffs_i[2][1] = (int)(mat->coeffs_f[2][1] * 65536.0 + 0.5);
1236 /* v -> v */
1237 mat->coeffs_i[2][2] = (int)(mat->coeffs_f[2][2] * 65536.0 + 0.5);
1238 /* a -> v */
1239 mat->coeffs_i[2][3] = (int)(mat->coeffs_f[2][3] * 65536.0 * SCALE_UV / SCALE_A + 0.5);
1240 /* v off */
1241 mat->coeffs_i[2][4] = (int)(mat->coeffs_f[2][4] * 65536.0 * SCALE_UV / SCALE_OFF + 0.5);
1242
1243 /* y -> a */
1244 mat->coeffs_i[3][0] = (int)(mat->coeffs_f[3][0] * 65536.0 * SCALE_A / SCALE_Y + 0.5);
1245 /* u -> a */
1246 mat->coeffs_i[3][1] = (int)(mat->coeffs_f[3][1] * 65536.0 * SCALE_A / SCALE_UV + 0.5);
1247 /* v -> a */
1248 mat->coeffs_i[3][2] = (int)(mat->coeffs_f[3][2] * 65536.0 * SCALE_A / SCALE_UV + 0.5);
1249 /* a -> a */
1250 mat->coeffs_i[3][3] = (int)(mat->coeffs_f[3][3] * 65536.0 + 0.5);
1251 /* a off */
1252 mat->coeffs_i[3][4] = (int)(mat->coeffs_f[3][4] * 65536.0 * SCALE_A / SCALE_OFF + 0.5);
1253 }
1254
1255
init_internal(bg_colormatrix_t * m)1256 static void init_internal(bg_colormatrix_t*m)
1257 {
1258 switch(m->format.pixelformat)
1259 {
1260 case GAVL_RGB_24:
1261 m->func = process_rgb_24;
1262 matrix_f_to_8(&m->rgba);
1263 break;
1264 case GAVL_RGB_48:
1265 m->func = process_rgb_48;
1266 matrix_f_to_16(&m->rgba);
1267 break;
1268 case GAVL_RGB_FLOAT:
1269 m->func = process_rgb_float;
1270 break;
1271 case GAVL_RGB_32:
1272 m->func = process_rgb_32;
1273 matrix_f_to_8(&m->rgba);
1274 break;
1275 case GAVL_BGR_24:
1276 m->func = process_bgr_24;
1277 matrix_f_to_8(&m->rgba);
1278 break;
1279 case GAVL_BGR_32:
1280 m->func = process_bgr_32;
1281 matrix_f_to_8(&m->rgba);
1282 break;
1283 case GAVL_RGBA_32:
1284 m->func = process_rgba_32;
1285 matrix_f_to_8(&m->rgba);
1286 break;
1287 case GAVL_RGBA_64:
1288 m->func = process_rgba_64;
1289 matrix_f_to_16(&m->rgba);
1290 break;
1291 case GAVL_RGBA_FLOAT:
1292 m->func = process_rgba_float;
1293 break;
1294 case GAVL_YUVJ_444_P:
1295 m->func = process_444j;
1296 matrix_f_to_8(&m->yuva);
1297 break;
1298 case GAVL_YUV_444_P:
1299 m->func = process_444;
1300 matrix_f_to_8_yuv(&m->yuva);
1301 break;
1302 case GAVL_YUVA_32:
1303 m->func = process_yuva_32;
1304 matrix_f_to_8_yuv(&m->yuva);
1305 break;
1306 case GAVL_YUV_444_P_16:
1307 m->func = process_444_16;
1308 matrix_f_to_16_yuv(&m->yuva);
1309 break;
1310 /* */
1311 case GAVL_GRAY_8:
1312 matrix_f_to_8(&m->yuva);
1313 m->func = process_gray_8;
1314 break;
1315 case GAVL_GRAY_16:
1316 matrix_f_to_16(&m->yuva);
1317 m->func = process_gray_16;
1318 break;
1319 case GAVL_GRAY_FLOAT:
1320 m->func = process_gray_float;
1321 break;
1322 case GAVL_GRAYA_16:
1323 matrix_f_to_8(&m->yuva);
1324 m->func = process_graya_16;
1325 break;
1326 case GAVL_GRAYA_32:
1327 matrix_f_to_16(&m->yuva);
1328 m->func = process_graya_32;
1329 break;
1330 case GAVL_GRAYA_FLOAT:
1331 m->func = process_graya_float;
1332 break;
1333 case GAVL_YUV_FLOAT:
1334 m->func = process_yuv_float;
1335 break;
1336 case GAVL_YUVA_FLOAT:
1337 m->func = process_yuva_float;
1338 break;
1339 case GAVL_YUVA_64:
1340 m->func = process_yuva_64;
1341 matrix_f_to_16_yuv(&m->yuva);
1342 break;
1343 default:
1344 break;
1345 }
1346 }
1347
1348
bg_colormatrix_set_rgba(bg_colormatrix_t * m,float coeffs[4][5])1349 void bg_colormatrix_set_rgba(bg_colormatrix_t * m, float coeffs[4][5])
1350 {
1351 colormatrix_set_4(coeffs, m->rgba.coeffs_f);
1352 colormatrix_rgb2yuv(m->rgba.coeffs_f, m->yuva.coeffs_f);
1353 init_internal(m);
1354 }
1355
bg_colormatrix_set_yuva(bg_colormatrix_t * m,float coeffs[4][5])1356 void bg_colormatrix_set_yuva(bg_colormatrix_t * m, float coeffs[4][5])
1357 {
1358 colormatrix_set_4(coeffs, m->yuva.coeffs_f);
1359 colormatrix_rgb2yuv(m->yuva.coeffs_f, m->rgba.coeffs_f);
1360 init_internal(m);
1361 }
1362
bg_colormatrix_set_rgb(bg_colormatrix_t * m,float coeffs[3][4])1363 void bg_colormatrix_set_rgb(bg_colormatrix_t * m, float coeffs[3][4])
1364 {
1365 colormatrix_set_3(coeffs, m->rgba.coeffs_f);
1366 colormatrix_rgb2yuv(m->rgba.coeffs_f, m->yuva.coeffs_f);
1367 init_internal(m);
1368 // dump_matrix(m->rgba.coeffs_f);
1369 // dump_matrix(m->yuva.coeffs_f);
1370 }
1371
bg_colormatrix_set_yuv(bg_colormatrix_t * m,float coeffs[3][4])1372 void bg_colormatrix_set_yuv(bg_colormatrix_t * m, float coeffs[3][4])
1373 {
1374 colormatrix_set_3(coeffs, m->yuva.coeffs_f);
1375 colormatrix_yuv2rgb(m->yuva.coeffs_f, m->rgba.coeffs_f);
1376 init_internal(m);
1377 }
1378
1379 static const gavl_pixelformat_t pixelformats[] =
1380 {
1381 GAVL_RGB_24,
1382 GAVL_RGB_48,
1383 GAVL_RGB_32,
1384 GAVL_BGR_24,
1385 GAVL_BGR_32,
1386 GAVL_RGBA_32,
1387 GAVL_RGBA_64,
1388 GAVL_RGB_FLOAT,
1389 GAVL_RGBA_FLOAT,
1390 GAVL_YUVJ_444_P,
1391 GAVL_YUV_444_P,
1392 GAVL_YUV_444_P_16,
1393 GAVL_YUVA_32,
1394 GAVL_GRAY_8,
1395 GAVL_GRAY_16,
1396 GAVL_GRAY_FLOAT,
1397 GAVL_GRAYA_16,
1398 GAVL_GRAYA_32,
1399 GAVL_GRAYA_FLOAT,
1400 GAVL_YUV_FLOAT,
1401 GAVL_YUVA_FLOAT,
1402 GAVL_YUVA_64,
1403 GAVL_PIXELFORMAT_NONE,
1404 };
1405
1406 static const gavl_pixelformat_t pixelformats_alpha[] =
1407 {
1408 GAVL_RGBA_32,
1409 GAVL_RGBA_64,
1410 GAVL_YUVA_32,
1411 GAVL_YUVA_FLOAT,
1412 GAVL_RGBA_FLOAT,
1413 GAVL_PIXELFORMAT_NONE,
1414 };
1415
1416
bg_colormatrix_init(bg_colormatrix_t * m,gavl_video_format_t * format,int flags,gavl_video_options_t * opt)1417 void bg_colormatrix_init(bg_colormatrix_t * m,
1418 gavl_video_format_t * format, int flags,
1419 gavl_video_options_t * opt)
1420 {
1421 m->run_func = gavl_video_options_get_run_func(opt, &m->run_data);
1422 m->stop_func = gavl_video_options_get_stop_func(opt, &m->stop_data);
1423 m->num_threads = gavl_video_options_get_num_threads(opt);
1424
1425 if(flags & BG_COLORMATRIX_FORCE_ALPHA)
1426 format->pixelformat = gavl_pixelformat_get_best(format->pixelformat,
1427 pixelformats_alpha,
1428 NULL);
1429 else
1430 format->pixelformat = gavl_pixelformat_get_best(format->pixelformat,
1431 pixelformats,
1432 NULL);
1433
1434 bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Pixelformat: %s",
1435 TRD(gavl_pixelformat_to_string(format->pixelformat), NULL));
1436
1437 gavl_video_format_copy(&m->format, format);
1438 init_internal(m);
1439
1440 }
1441
bg_colormatrix_process(bg_colormatrix_t * m,gavl_video_frame_t * in_frame)1442 void bg_colormatrix_process(bg_colormatrix_t * m,
1443 gavl_video_frame_t * in_frame)
1444 {
1445 int j, nt, scanline, delta;
1446
1447 m->frame = in_frame;
1448
1449 nt = m->num_threads;
1450 if(nt > m->format.image_height)
1451 nt = m->format.image_height;
1452
1453 delta = m->format.image_height / nt;
1454 scanline = 0;
1455
1456 for(j = 0; j < nt - 1; j++)
1457 {
1458 m->run_func(m->func, m, scanline, scanline+delta, m->run_data, j);
1459 scanline += delta;
1460 }
1461 m->run_func(m->func, m, scanline, m->format.image_height,
1462 m->run_data, nt - 1);
1463
1464 for(j = 0; j < nt; j++)
1465 m->stop_func(m->stop_data, j);
1466 }
1467
1468