Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcxfer.h
1 /*
2  * CINELERRA
3  * Copyright (C) 2016-2020 William Morrow
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published
7  * by the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20
21
22 #include "bccmodels.h"
23 #include "bcresources.h"
24 #include "condition.h"
25 #include "linklist.h"
26 #include "mutex.h"
27 #include "thread.h"
28 #include "clip.h"
29
30 static inline float clp(const int n, float v) {
31  v *= ((float)(n*(1-1./0x1000000)));
32  return v < 0 ? 0 : v >= n ? n-1 : v;
33 }
34
35 static inline float fclp(float v, const int n) {
36  v /= ((float)(n*(1-1./0x1000000)));
37  return v < 0 ? 0 : v > 1 ? 1 : v;
38 }
39
40 #include <stdint.h>
41
42 #define ZTYP(ty) typedef ty z_##ty __attribute__ ((__unused__))
43 ZTYP(int);
44 ZTYP(float);
45
46
47 #define xfer_flat_row_out(oty_t) \
48   for( unsigned i=y0; i<y1; ++i ) { \
49     oty_t *out = (oty_t *)(output_rows[i + out_y] + out_x * out_pixelsize); \
50
51 #define xfer_flat_row_in(ity_t) \
52     uint8_t *inp_row = input_rows[row_table[i]]; \
53     for( unsigned j=0; j<out_w; ++j ) { \
54       ity_t *inp = (ity_t *)(inp_row + column_table[j]); \
55
56 #define xfer_clear(s) \
57     for( unsigned j=0; j<out_w; ++j ) { \
58
59 #define xfer_end } }
60
61 // yuv420p  2x2
62 #define xfer_yuv420p_row_out(oty_t) \
63   for( unsigned i=y0; i<y1; ++i ) { \
64     int out_rofs = i * total_out_w + out_x; \
65     oty_t *yop = (oty_t *)(out_yp + out_rofs); \
66     out_rofs = i / 2 * total_out_w / 2 + out_x / 2; \
67     oty_t *uop = (oty_t *)(out_up + out_rofs); \
68     oty_t *vop = (oty_t *)(out_vp + out_rofs); \
69
70 #define xfer_yuv420p_row_in(ity_t) \
71     int in_r = row_table[i]; \
72     int in_rofs = in_r * total_in_w; \
73     uint8_t *yip_row = in_yp + in_rofs; \
74     in_rofs = in_r / 2 * total_in_w / 2; \
75     uint8_t *uip_row = in_up + in_rofs; \
76     uint8_t *vip_row = in_vp + in_rofs; \
77     for( unsigned j=0; j<out_w; ++j ) { \
78       int in_ofs = column_table[j]; \
79       ity_t *yip = (ity_t *)(yip_row + in_ofs); \
80       in_ofs /= 2; \
81       ity_t *uip = (ity_t *)(uip_row + in_ofs); \
82       ity_t *vip = (ity_t *)(vip_row + in_ofs); \
83
84 // yuv420pi  2x2
85 #define xfer_yuv420pi_row_out(oty_t) \
86   for( unsigned i=y0; i<y1; ++i ) { \
87     int out_rofs = i * total_out_w + out_x; \
88     oty_t *yop = (oty_t *)(out_yp + out_rofs); \
89     int ot_k = ((i/4)<<1) + (i&1); \
90     out_rofs = ot_k * total_out_w / 2 + out_x / 2; \
91     oty_t *uop = (oty_t *)(out_up + out_rofs); \
92     oty_t *vop = (oty_t *)(out_vp + out_rofs); \
93
94 #define xfer_yuv420pi_row_in(ity_t) \
95     int in_r = row_table[i]; \
96     int in_rofs = in_r * total_in_w; \
97     uint8_t *yip_row = in_yp + in_rofs; \
98     int in_k = ((in_r/4)<<1) + (in_r&1); \
99     in_rofs = in_k * total_in_w / 2; \
100     uint8_t *uip_row = in_up + in_rofs; \
101     uint8_t *vip_row = in_vp + in_rofs; \
102     for( unsigned j=0; j<out_w; ++j ) { \
103       int in_ofs = column_table[j]; \
104       ity_t *yip = (ity_t *)(yip_row + in_ofs); \
105       in_ofs /= 2; \
106       ity_t *uip = (ity_t *)(uip_row + in_ofs); \
107       ity_t *vip = (ity_t *)(vip_row + in_ofs); \
108
109 // yuv422p  2x1
110 #define xfer_yuv422p_row_out(oty_t) \
111   for( unsigned i=y0; i<y1; ++i ) { \
112     int out_rofs = i * total_out_w + out_x; \
113     oty_t *yop = (oty_t *)(out_yp + out_rofs); \
114     out_rofs = i * total_out_w / 2 + out_x / 2; \
115     oty_t *uop = (oty_t *)(out_up + out_rofs); \
116     oty_t *vop = (oty_t *)(out_vp + out_rofs); \
117
118 #define xfer_yuv422p_row_in(ity_t) \
119     int in_rofs = row_table[i] * total_in_w; \
120     uint8_t *yip_row = in_yp + in_rofs; \
121     in_rofs /= 2; \
122     uint8_t *uip_row = in_up + in_rofs; \
123     uint8_t *vip_row = in_vp + in_rofs; \
124     for( unsigned j=0; j<out_w; ++j ) { \
125       int in_ofs = column_table[j]; \
126       ity_t *yip = (ity_t *)(yip_row + in_ofs); \
127       in_ofs /= 2; \
128       ity_t *uip = (ity_t *)(uip_row + in_ofs); \
129       ity_t *vip = (ity_t *)(vip_row + in_ofs); \
130
131 // yuv444p  1x1
132 #define xfer_yuv444p_row_out(oty_t) \
133   for( unsigned i=y0; i<y1; ++i ) { \
134     int out_rofs = i * total_out_w + out_x; \
135     oty_t *yop = (oty_t *)((oty_t *)(out_yp + out_rofs)); \
136     oty_t *uop = (oty_t *)(out_up + out_rofs); \
137     oty_t *vop = (oty_t *)(out_vp + out_rofs); \
138
139 #define xfer_yuv444p_row_in(ity_t) \
140     int in_rofs = row_table[i] * total_in_w; \
141     uint8_t *yip_row = in_yp + in_rofs; \
142     uint8_t *uip_row = in_up + in_rofs; \
143     uint8_t *vip_row = in_vp + in_rofs; \
144     for( unsigned j=0; j<out_w; ++j ) { \
145       int in_ofs = column_table[j]; \
146       ity_t *yip = (ity_t *)(yip_row + in_ofs); \
147       ity_t *uip = (ity_t *)(uip_row + in_ofs); \
148       ity_t *vip = (ity_t *)(vip_row + in_ofs); \
149
150 // yuv411p  4x1
151 #define xfer_yuv411p_row_out(oty_t) \
152   for( unsigned i=y0; i<y1; ++i ) { \
153     int out_rofs = i * total_out_w + out_x; \
154     oty_t *yop = (oty_t *)(out_yp + out_rofs); \
155     out_rofs = i * total_out_w / 4 + out_x / 4; \
156     oty_t *uop = (oty_t *)(out_up + out_rofs); \
157     oty_t *vop = (oty_t *)(out_vp + out_rofs); \
158
159 #define xfer_yuv411p_row_in(ity_t) \
160     int in_rofs = row_table[i] * total_in_w; \
161     uint8_t *yip_row = in_yp + in_rofs; \
162     in_rofs /= 4; \
163     uint8_t *uip_row = in_up + in_rofs; \
164     uint8_t *vip_row = in_vp + in_rofs; \
165     for( unsigned j=0; j<out_w; ++j ) { \
166       int in_ofs = column_table[j]; \
167       ity_t *yip = (ity_t *)(yip_row + in_ofs); \
168       in_ofs /= 4; \
169       ity_t *uip = (ity_t *)(uip_row + in_ofs); \
170       ity_t *vip = (ity_t *)(vip_row + in_ofs); \
171
172 // yuv410p  4x4
173 #define xfer_yuv410p_row_out(oty_t) \
174   for( unsigned i=y0; i<y1; ++i ) { \
175     int out_rofs = i * total_out_w + out_x; \
176     oty_t *yop = (oty_t *)(out_yp + out_rofs); \
177     out_rofs = i / 4 * total_out_w / 4 + out_x / 4; \
178     oty_t *uop = (oty_t *)(out_up + out_rofs); \
179     oty_t *vop = (oty_t *)(out_vp + out_rofs); \
180
181 #define xfer_yuv410p_row_in(ity_t) \
182     int in_rofs = row_table[i] * total_in_w; \
183     uint8_t *yip_row = in_yp + in_rofs; \
184     in_rofs = row_table[i] / 4 * total_in_w / 4; \
185     uint8_t *uip_row = in_up + in_rofs; \
186     uint8_t *vip_row = in_vp + in_rofs; \
187     for( unsigned j=0; j<out_w; ++j ) { \
188       int in_ofs = column_table[j]; \
189       ity_t *yip = (ity_t *)(yip_row + in_ofs); \
190       in_ofs /= 4; \
191       ity_t *uip = (ity_t *)(uip_row + in_ofs); \
192       ity_t *vip = (ity_t *)(vip_row + in_ofs); \
193
194 // rgb planar
195 #define xfer_rgbp_row_out(oty_t) \
196   for( unsigned i=y0; i<y1; ++i ) { \
197     int out_rofs = i * total_out_w + out_x; \
198     oty_t *rop = (oty_t *)(out_yp + out_rofs); \
199     oty_t *gop = (oty_t *)(out_up + out_rofs); \
200     oty_t *bop = (oty_t *)(out_vp + out_rofs); \
201
202 #define xfer_rgbap_row_out(oty_t) \
203   xfer_rgbp_row_out(oty_t) \
204     oty_t *aop = (oty_t *)(out_ap + out_rofs); \
205
206
207 #define xfer_row_in_rgbp(ity_t) \
208     int in_rofs = row_table[i] * total_in_w; \
209     uint8_t *rip_row = in_yp + in_rofs; \
210     uint8_t *gip_row = in_up + in_rofs; \
211     uint8_t *bip_row = in_vp + in_rofs; \
212
213 #define xfer_row_in_rgbap(oty_t) \
214   xfer_row_in_rgbp(ity_t) \
215     uint8_t *aip_row = in_ap + in_rofs; \
216
217
218 #define xfer_col_in_rgbp(ity_t) \
219     for( unsigned j=0; j<out_w; ++j ) { \
220       int in_ofs = column_table[j]; \
221       ity_t *rip = (ity_t *)(rip_row + in_ofs); \
222       ity_t *gip = (ity_t *)(gip_row + in_ofs); \
223       ity_t *bip = (ity_t *)(bip_row + in_ofs); \
224
225 #define xfer_col_in_rgbap(ity_t) \
226   xfer_col_in_rgbp(ity_t) \
227     ity_t *aip = (ity_t *)(aip_row + in_ofs); \
228
229
230 #define xfer_rgbp_row_in(ity_t) \
231   xfer_row_in_rgbp(ity_t) \
232     xfer_col_in_rgbp(ity_t) \
233
234 #define xfer_rgbap_row_in(ity_t) \
235   xfer_row_in_rgbap(ity_t) \
236     xfer_col_in_rgbap(ity_t) \
237
238
239 class BC_Xfer {
240   BC_Xfer(const BC_Xfer&) {}
241 public:
242   BC_Xfer(uint8_t **output_rows, uint8_t **input_rows,
243   uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp,
244   uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp,
245   int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h,
246   int in_colormodel, int out_colormodel, int bg_color, int bg_alpha,
247   int in_rowspan, int out_rowspan);
248   BC_Xfer(uint8_t **output_ptrs, int out_colormodel,
249       int out_x, int out_y, int out_w, int out_h, int out_rowspan,
250     uint8_t **input_ptrs, int in_colormodel,
251       int in_x, int in_y, int in_w, int in_h, int in_rowspan,
252     int bg_color, int bg_alpha);
253   ~BC_Xfer();
254
255   uint8_t **output_rows, **input_rows;
256   uint8_t *out_yp, *out_up, *out_vp, *out_ap;
257   uint8_t *in_yp, *in_up, *in_vp, *in_ap;
258   int in_x, in_y; unsigned in_w, in_h;
259   int out_x, out_y; unsigned out_w, out_h;
260   int in_colormodel, out_colormodel;
261   uint32_t total_in_w, total_out_w;
262   int scale;
263   int out_pixelsize, in_pixelsize;
264   int *row_table, *column_table;
265   uint32_t bg_r, bg_g, bg_b, bg_a;
266   float bg_fr, bg_fg, bg_fb, bg_fa;
267
268   int xfer();
269   int xfer_slices(int slices);
270   typedef void (BC_Xfer::*xfer_fn)(unsigned y0, unsigned y1);
271   xfer_fn xfn;
272
273   class Slicer : public ListItem<Slicer>, public Thread {
274   public:
275     Condition *init, *complete;
276     Slicer(BC_Xfer *xp);
277     ~Slicer();
278     void slice(BC_Xfer *xp, unsigned y0, unsigned y1);
279     void run();
280     BC_Xfer *xp;
281     int done, y0, y1;
282   };
283
284   class SlicerList : public List<Slicer>, public Mutex {
285   public:
286     int count;
287     Slicer *get_slicer(BC_Xfer *xp);
288     void reset();
289     SlicerList();
290     ~SlicerList();
291   };
292   static SlicerList slicers;
293
294   void init(
295     uint8_t **output_rows, int out_colormodel, int out_x, int out_y, int out_w, int out_h,
296       uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp, uint8_t *out_ap, int out_rowspan,
297     uint8_t **input_rows, int in_colormodel, int in_x, int in_y, int in_w, int in_h,
298       uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp, uint8_t *in_ap, int in_rowspan,
299     int bg_color, int bg_alpha);
300
301 // generated code concatentated here