mixer undo fix, new ffmpeg opts, docs
[goodguy/history.git] / cinelerra-5.1 / plugins / downsample / downsampleengine.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22
23
24 #include "clip.h"
25 #include "downsampleengine.h"
26 #include "vframe.h"
27
28
29 #include <stdint.h>
30
31 DownSamplePackage::DownSamplePackage()
32  : LoadPackage()
33 {
34 }
35
36
37
38
39 DownSampleUnit::DownSampleUnit(DownSampleServer *server)
40  : LoadClient(server)
41 {
42         this->server = server;
43 }
44
45
46
47 #define DOWNSAMPLE(type, temp_type, components, max) \
48 { \
49         temp_type r; \
50         temp_type g; \
51         temp_type b; \
52         temp_type a; \
53         int do_r = server->r; \
54         int do_g = server->g; \
55         int do_b = server->b; \
56         int do_a = server->a; \
57         type **in_rows = (type**)server->input->get_rows(); \
58         type **out_rows = (type**)server->output->get_rows(); \
59  \
60         for(int i = pkg->y1; i < pkg->y2; i += server->vertical) \
61         { \
62                 int y1 = MAX(i, 0); \
63                 int y2 = MIN(i + server->vertical, h); \
64  \
65  \
66                 for(int j = server->horizontal_x - server->horizontal; \
67                         j < w; \
68                         j += server->horizontal) \
69                 { \
70                         int x1 = MAX(j, 0); \
71                         int x2 = MIN(j + server->horizontal, w); \
72  \
73                         temp_type scale = (x2 - x1) * (y2 - y1); \
74                         if(x2 > x1 && y2 > y1) \
75                         { \
76  \
77 /* Read in values */ \
78                                 r = 0; \
79                                 g = 0; \
80                                 b = 0; \
81                                 if(components == 4) a = 0; \
82  \
83                                 for(int k = y1; k < y2; k++) \
84                                 { \
85                                         type *row = in_rows[k] + x1 * components; \
86                                         for(int l = x1; l < x2; l++) \
87                                         { \
88                                                 if(do_r) r += *row++; else row++; \
89                                                 if(do_g) g += *row++; else row++;  \
90                                                 if(do_b) b += *row++; else row++;  \
91                                                 if(components == 4) \
92                                                 { \
93                                                         if(do_a) *row = a; \
94                                                          row++; \
95                                                 } \
96                                         } \
97                                 } \
98  \
99 /* Write average */ \
100                                 r /= scale; \
101                                 g /= scale; \
102                                 b /= scale; \
103                                 if(components == 4) a /= scale; \
104                                 for(int k = y1; k < y2; k++) \
105                                 { \
106                                         type *row = out_rows[k] + x1 * components; \
107                                         for(int l = x1; l < x2; l++) \
108                                         { \
109                                                 if(do_r) *row++ = r; else row++; \
110                                                 if(do_g) *row++ = g; else row++; \
111                                                 if(do_b) *row++ = b; else row++; \
112                                                 if(components == 4) \
113                                                 { \
114                                                         if(do_a) *row = a; \
115                                                          row++; \
116                                                 } \
117                                         } \
118                                 } \
119                         } \
120                 } \
121 /*printf("DOWNSAMPLE 3 %d\n", i);*/ \
122         } \
123 }
124
125 void DownSampleUnit::process_package(LoadPackage *package)
126 {
127         DownSamplePackage *pkg = (DownSamplePackage*)package;
128         int h = server->output->get_h();
129         int w = server->output->get_w();
130
131
132         switch(server->input->get_color_model())
133         {
134                 case BC_RGB888:
135                         DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
136                         break;
137                 case BC_RGB_FLOAT:
138                         DOWNSAMPLE(float, float, 3, 1.0)
139                         break;
140                 case BC_RGBA8888:
141                         DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
142                         break;
143                 case BC_RGBA_FLOAT:
144                         DOWNSAMPLE(float, float, 4, 1.0)
145                         break;
146                 case BC_RGB161616:
147                         DOWNSAMPLE(uint16_t, int64_t, 3, 0xffff)
148                         break;
149                 case BC_RGBA16161616:
150                         DOWNSAMPLE(uint16_t, int64_t, 4, 0xffff)
151                         break;
152                 case BC_YUV888:
153                         DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
154                         break;
155                 case BC_YUVA8888:
156                         DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
157                         break;
158                 case BC_YUV161616:
159                         DOWNSAMPLE(uint16_t, int64_t, 3, 0xffff)
160                         break;
161                 case BC_YUVA16161616:
162                         DOWNSAMPLE(uint16_t, int64_t, 4, 0xffff)
163                         break;
164         }
165 }
166
167
168
169
170
171
172 DownSampleServer::DownSampleServer(int total_clients,
173         int total_packages)
174  : LoadServer(total_clients, total_packages)
175 {
176 }
177
178 void DownSampleServer::init_packages()
179 {
180         int y1 = vertical_y - vertical;
181         int total_strips = (int)((float)output->get_h() / vertical + 1);
182         int strips_per_package = (int)((float)total_strips / get_total_packages() + 1);
183
184         for(int i = 0; i < get_total_packages(); i++)
185         {
186                 DownSamplePackage *package = (DownSamplePackage*)get_package(i);
187                 package->y1 = y1;
188                 package->y2 = y1 + strips_per_package * vertical;
189                 package->y1 = MIN(output->get_h(), package->y1);
190                 package->y2 = MIN(output->get_h(), package->y2);
191                 y1 = package->y2;
192         }
193 }
194
195 LoadClient* DownSampleServer::new_client()
196 {
197         return new DownSampleUnit(this);
198 }
199
200 LoadPackage* DownSampleServer::new_package()
201 {
202         return new DownSamplePackage;
203 }
204
205 void DownSampleServer::process_frame(VFrame *output,
206         VFrame *input,
207         int r,
208         int g,
209         int b,
210         int a,
211         int vertical,
212         int horizontal,
213         int vertical_y,
214         int horizontal_x)
215 {
216         this->input = input;
217         this->output = output;
218         this->r = r;
219         this->g = g;
220         this->b = b;
221         this->a = a;
222         this->vertical = vertical;
223         this->vertical_y = vertical_y;
224         this->horizontal = horizontal;
225         this->horizontal_x = horizontal_x;
226
227         process_packages();
228 }
229
230
231
232
233
234