4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bccmodels.h"
32 unsigned int EffectTV::fastrand_val = 0;
34 EffectTV::EffectTV(int w, int h)
38 background = (unsigned char*)new uint16_t[w * h];
39 diff = new unsigned char[w * h];
40 diff2 = new unsigned char[w * h];
54 int EffectTV::yuv_init()
58 for(i = 0; i < 256; i++)
60 YtoRGB[i] = (int)( 1.164 * (i - 16));
61 VtoR[i] = (int)( 1.596 * (i - 128));
62 VtoG[i] = (int)(-0.813 * (i - 128));
63 UtoG[i] = (int)(-0.391 * (i - 128));
64 UtoB[i] = (int)( 2.018 * (i - 128));
65 RtoY[i] = (int)( 0.257 * i);
66 RtoU[i] = (int)(-0.148 * i);
67 RtoV[i] = (int)( 0.439 * i);
68 GtoY[i] = (int)( 0.504 * i);
69 GtoU[i] = (int)(-0.291 * i);
70 GtoV[i] = (int)(-0.368 * i);
71 BtoY[i] = (int)( 0.098 * i);
72 BtoV[i] = (int)(-0.071 * i);
73 //printf("EffectTV::yuv_init %d %d %d\n", RtoY[i], GtoY[i], BtoY[i]);
79 #define FRAME_TO_EFFECTTV(type, components) \
81 for(int i = 0; i < width; i++) \
83 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
84 type *input_row = ((type**)frame->get_rows())[i]; \
86 for(int j = 0; j < width; j++) \
88 if(sizeof(type) == 1) \
90 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 16; \
91 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]) << 8; \
92 row[j * sizeof(uint32_t)] |= input_row[2]; \
96 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 8; \
97 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]); \
98 row[j * sizeof(uint32_t)] |= input_row[2] >> 8; \
100 input_row += components; \
107 void EffectTV::frame_to_effecttv(VFrame *frame, uint32_t *tmp)
109 int width = frame->get_w();
110 //int height = frame->get_h();
112 switch(frame->get_color_model())
116 FRAME_TO_EFFECTTV(uint8_t, 3);
121 FRAME_TO_EFFECTTV(uint8_t, 4);
126 FRAME_TO_EFFECTTV(uint16_t, 3);
129 case BC_RGBA16161616:
130 case BC_YUVA16161616:
131 FRAME_TO_EFFECTTV(uint16_t, 4);
138 #define EFFECTTV_TO_FRAME(type, components, alpha) \
140 for(int i = 0; i < width; i++) \
142 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
143 type *output_row = ((type**)frame->get_rows())[i]; \
145 for(int j = 0; j < width; j++) \
147 if(sizeof(type) == 1) \
149 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 16; \
150 output_row[1] = (row[j * sizeof(uint32_t)] & 0xff00) >> 8; \
151 output_row[2] = row[j * sizeof(uint32_t)] & 0xff; \
152 if(components == 4) output_row[3] = alpha; \
156 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 8; \
157 output_row[1] = row[j * sizeof(uint32_t)] & 0xff00; \
158 output_row[2] = (row[j * sizeof(uint32_t)] & 0xff) << 8; \
159 if(components == 4) output_row[3] = alpha; \
161 output_row += components; \
168 void EffectTV::effecttv_to_frame(VFrame *frame, uint32_t *tmp)
170 int width = frame->get_w();
171 //int height = frame->get_h();
173 switch(frame->get_color_model())
177 EFFECTTV_TO_FRAME(uint8_t, 3, 0xff);
182 EFFECTTV_TO_FRAME(uint8_t, 4, 0xff);
187 EFFECTTV_TO_FRAME(uint16_t, 3, 0xffff);
190 case BC_RGBA16161616:
191 case BC_YUVA16161616:
192 EFFECTTV_TO_FRAME(uint16_t, 4, 0xffff);
199 void EffectTV::image_set_threshold_y(int threshold)
201 y_threshold = threshold * 7; /* fake-Y value is timed by 7 */
206 /* Background image is refreshed every frame */
208 IMAGE_BGSUBTRACT_UPDATE_Y(type, components, is_yuv) \
217 q = (int16_t *)background; \
220 for(i = 0; i < h; i++) \
222 p = (type*)input_rows[i]; \
224 for(j = 0; j < w; j++) \
226 if(is_yuv && sizeof(type) == 2) \
228 R = G = B = (int)p[0] >> 8; \
233 if(is_yuv && sizeof(type) == 1) \
235 R = G = B = (int)p[0]; \
240 if(sizeof(type) == 4) \
242 R = (int)(p[0] * 0x1ff); \
243 G = (int)(p[1] * 0x3ff); \
244 B = (int)(p[2] * 0xff); \
245 CLAMP(R, 0, 0x1ff); \
246 CLAMP(G, 0, 0x3ff); \
250 if(sizeof(type) == 2) \
252 R = (int)p[0] >> (8 - 1); \
253 G = (int)p[1] >> (8 - 2); \
254 B = (int)p[2] >> 8; \
258 R = (int)p[0] << 1; \
259 G = (int)p[1] << 2; \
263 v = (R + G + B) - (int)(*q); \
264 *q = (int16_t)(R + G + B); \
265 *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
280 unsigned char* EffectTV::image_bgsubtract_update_y(unsigned char **input_rows,
281 unsigned char **output_rows,
287 IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 3, 0);
290 IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 3, 1);
293 IMAGE_BGSUBTRACT_UPDATE_Y(float, 3, 0);
296 IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 4, 0);
299 IMAGE_BGSUBTRACT_UPDATE_Y(float, 4, 0);
302 IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 4, 1);
305 IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 3, 0);
308 IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 3, 1);
310 case BC_RGBA16161616:
311 IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 4, 0);
313 case BC_YUVA16161616:
314 IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 4, 1);
326 #define IMAGE_BGSUBTRACT_Y(type, components, is_yuv) \
332 for(i = 0; i < h; i++) \
334 p = (type*)input_rows[i]; \
336 for(j = 0; j < w; j++) \
338 if(is_yuv && sizeof(type) == 2) \
340 R = G = B = (int)p[0] >> 8; \
345 if(is_yuv && sizeof(type) == 1) \
347 R = G = B = (int)p[0]; \
352 if(sizeof(type) == 4) \
354 R = (int)(p[0] * 0x1ff); \
355 G = (int)(p[1] * 0x3ff); \
356 B = (int)(p[2] * 0xff); \
357 CLAMP(R, 0, 0x1ff); \
358 CLAMP(G, 0, 0x3ff); \
362 if(sizeof(type) == 2) \
364 R = (int)p[0] >> (8 - 1); \
365 G = (int)p[1] >> (8 - 2); \
366 B = (int)p[2] >> 8; \
370 R = (int)p[0] << 1; \
371 G = (int)p[1] << 2; \
375 v = (R + G + B) - (int)(*q); \
376 *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
386 unsigned char* EffectTV::image_bgsubtract_y(unsigned char **input_rows,
393 q = (int16_t *)background;
401 IMAGE_BGSUBTRACT_Y(uint8_t, 3, 0);
404 IMAGE_BGSUBTRACT_Y(uint8_t, 3, 1);
407 IMAGE_BGSUBTRACT_Y(float, 3, 0);
410 IMAGE_BGSUBTRACT_Y(float, 4, 0);
413 IMAGE_BGSUBTRACT_Y(uint8_t, 4, 0);
416 IMAGE_BGSUBTRACT_Y(uint8_t, 4, 1);
419 IMAGE_BGSUBTRACT_Y(uint16_t, 3, 0);
422 IMAGE_BGSUBTRACT_Y(uint16_t, 3, 1);
424 case BC_RGBA16161616:
425 IMAGE_BGSUBTRACT_Y(uint16_t, 4, 0);
427 case BC_YUVA16161616:
428 IMAGE_BGSUBTRACT_Y(uint16_t, 4, 1);
439 /* The origin of subtraction function is;
440 * diff(src, dest) = (abs(src - dest) > threshold) ? 0xff : 0;
442 * This functions is transformed to;
443 * (threshold > (src - dest) > -threshold) ? 0 : 0xff;
445 * (v + threshold)>>24 is 0xff when v is less than -threshold.
446 * (v - threshold)>>24 is 0xff when v is less than threshold.
447 * So, ((v + threshold)>>24) | ((threshold - v)>>24) will become 0xff when
448 * abs(src - dest) > threshold.
457 unsigned char* EffectTV::image_diff_filter(unsigned char *diff)
460 unsigned char *src, *dest;
462 unsigned int sum1, sum2, sum3;
467 dest = diff2 + width + 1;
468 for(y = 1; y < height - 1; y++)
470 sum1 = src[0] + src[width] + src[width * 2];
471 sum2 = src[1] + src[width + 1] + src[width * 2 + 1];
474 for(x = 1; x < width - 1; x++)
476 sum3 = src[0] + src[width] + src[width * 2];
477 count = sum1 + sum2 + sum3;
480 *dest++ = (0xff * 3 - count) >> 24;
495 #define IMAGE_BGSET_Y(type, components, is_yuv) \
501 int width = frame->get_w(); \
502 int height = frame->get_h(); \
504 q = (int16_t *)background; \
508 for(i = 0; i < height; i++) \
510 p = (type*)frame->get_rows()[i]; \
512 for(j = 0; j < width; j++) \
514 if(is_yuv && sizeof(type) == 2) \
516 R = G = B = (int)p[0] >> 8; \
521 if(is_yuv && sizeof(type) == 1) \
523 R = G = B = (int)p[0]; \
528 if(sizeof(type) == 4) \
530 R = (int)(p[0] * 0x1ff); \
531 G = (int)(p[1] * 0x3ff); \
532 B = (int)(p[2] * 0xff); \
533 CLAMP(R, 0, 0x1ff); \
534 CLAMP(G, 0, 0x3ff); \
538 if(sizeof(type) == 2) \
540 R = (int)p[0] >> (8 - 1); \
541 G = (int)p[1] >> (8 - 2); \
542 B = (int)p[2] >> 8; \
546 R = (int)p[0] << 1; \
547 G = (int)p[1] << 2; \
551 *q = (int16_t)(R + G + B); \
564 void EffectTV::image_bgset_y(VFrame *frame)
566 switch(frame->get_color_model())
569 IMAGE_BGSET_Y(uint8_t, 3, 0);
572 IMAGE_BGSET_Y(float, 3, 0);
575 IMAGE_BGSET_Y(uint8_t, 3, 1);
578 IMAGE_BGSET_Y(uint8_t, 3, 0);
581 IMAGE_BGSET_Y(float, 3, 0);
584 IMAGE_BGSET_Y(uint8_t, 3, 1);
587 IMAGE_BGSET_Y(uint16_t, 3, 0);
590 IMAGE_BGSET_Y(uint16_t, 3, 1);
592 case BC_RGBA16161616:
593 IMAGE_BGSET_Y(uint16_t, 4, 0);
595 case BC_YUVA16161616:
596 IMAGE_BGSET_Y(uint16_t, 4, 1);