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