add view thumbnail size pref, rework vicon view popup, add view popup zoom scale
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcxfer.C
1
2 void BC_Xfer::init(
3         uint8_t **output_rows, int out_colormodel, int out_x, int out_y, int out_w, int out_h,
4                 uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp, uint8_t *out_ap, int out_rowspan,
5         uint8_t **input_rows, int in_colormodel, int in_x, int in_y, int in_w, int in_h,
6                 uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp, uint8_t *in_ap, int in_rowspan,
7         int bg_color)
8 {
9         this->bg_color = bg_color;
10         if( bg_color >= 0 ) {
11                 this->bg_r = (bg_color>>16) & 0xff;
12                 this->bg_g = (bg_color>>8) & 0xff;
13                 this->bg_b = (bg_color>>0) & 0xff;
14         }
15         else { // bg_color < 0, no src blending
16                 switch( in_colormodel ) {
17                 case BC_RGBA8888:       in_colormodel = BC_RGBX8888;            break;
18                 case BC_RGBA16161616:   in_colormodel = BC_RGBX16161616;        break;
19                 case BC_YUVA8888:       in_colormodel = BC_YUVX8888;            break;
20                 case BC_YUVA16161616:   in_colormodel = BC_YUVX16161616;        break;
21                 case BC_RGBA_FLOAT:     in_colormodel = BC_RGBX_FLOAT;          break;
22                 }
23         }
24         // prevent bounds errors on poorly dimensioned macro pixel formats
25         switch( in_colormodel ) {
26         case BC_UVY422:
27         case BC_YUV422:   in_w &= ~1;               break;  // 2x1
28         case BC_YUV420P:
29         case BC_YUV420PI: in_w &= ~1;  in_h &= ~1;  break;  // 2x2
30         case BC_YUV422P:  in_w &= ~1;               break;  // 2x1
31         case BC_YUV410P:  in_w &= ~3;  in_h &= ~3;  break;  // 4x4
32         case BC_YUV411P:  in_w &= ~3;               break;  // 4x1
33         }
34         switch( out_colormodel ) {
35         case BC_UVY422:
36         case BC_YUV422:  out_w &= ~1;               break;
37         case BC_YUV420P:
38         case BC_YUV420PI: out_w &= ~1; out_h &= ~1; break;
39         case BC_YUV422P: out_w &= ~1;               break;
40         case BC_YUV410P: out_w &= ~3; out_h &= ~3;  break;
41         case BC_YUV411P: out_w &= ~3;               break;
42         }
43         this->output_rows = output_rows;
44         this->input_rows = input_rows;
45         this->out_yp = out_yp;
46         this->out_up = out_up;
47         this->out_vp = out_vp;
48         this->out_ap = out_ap;
49         this->in_yp = in_yp;
50         this->in_up = in_up;
51         this->in_vp = in_vp;
52         this->in_ap = in_ap;
53         this->in_x = in_x;
54         this->in_y = in_y;
55         this->in_w = in_w;
56         this->in_h = in_h;
57         this->out_x = out_x;
58         this->out_y = out_y;
59         this->out_w = out_w;
60         this->out_h = out_h;
61         this->in_colormodel = in_colormodel;
62         switch( in_colormodel ) {
63         case BC_GBRP:
64                 in_rowspan = in_w * sizeof(uint8_t);
65                 break;
66         case BC_RGB_FLOATP:
67         case BC_RGBA_FLOATP:
68                 if( !BC_CModels::has_alpha(out_colormodel) )
69                         this->in_colormodel = BC_RGB_FLOATP;
70                 in_rowspan = in_w * sizeof(float);
71                 break;
72         }
73         this->total_in_w = in_rowspan;
74         this->out_colormodel = out_colormodel;
75         switch( out_colormodel ) {
76         case BC_GBRP:
77                 out_rowspan = out_w * sizeof(uint8_t);
78                 break;
79         case BC_RGB_FLOATP:
80         case BC_RGBA_FLOATP:
81                 out_rowspan = out_w * sizeof(float);
82                 break;
83         }
84         this->total_out_w = out_rowspan;
85         this->in_pixelsize = BC_CModels::calculate_pixelsize(in_colormodel);
86         this->out_pixelsize = BC_CModels::calculate_pixelsize(out_colormodel);
87         this->scale = (out_w != in_w) || (in_x != 0);
88
89 /* + 1 so we don't overflow when calculating in advance */
90         column_table = new int[out_w+1];
91         double hscale = (double)in_w/out_w;
92         for( int i=0; i<out_w; ++i ) {
93                         column_table[i] = ((int)(hscale * i) + in_x) * in_pixelsize;
94                         if( in_colormodel == BC_YUV422 || in_colormodel == BC_UVY422 )
95                                 column_table[i] &= ~3;
96         }
97         double vscale = (double)in_h/out_h;
98         row_table = new int[out_h];
99         for( int i=0; i<out_h; ++i )
100                 row_table[i] = (int)(vscale * i) + in_y;
101 }
102
103 BC_Xfer::BC_Xfer(uint8_t **output_rows, uint8_t **input_rows,
104         uint8_t *out_yp, uint8_t *out_up, uint8_t *out_vp,
105         uint8_t *in_yp, uint8_t *in_up, uint8_t *in_vp,
106         int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h,
107         int in_colormodel, int out_colormodel, int bg_color, int in_rowspan, int out_rowspan)
108 {
109         init(output_rows, out_colormodel, out_x, out_y, out_w, out_h,
110                 out_yp, out_up, out_vp, 0, out_rowspan,
111              input_rows, in_colormodel, in_x, in_y, in_w, in_h,
112                 in_yp, in_up, in_vp, 0, in_rowspan,  bg_color);
113 }
114
115 BC_Xfer::BC_Xfer(
116         uint8_t **output_ptrs, int out_colormodel,
117                 int out_x, int out_y, int out_w, int out_h, int out_rowspan,
118         uint8_t **input_ptrs, int in_colormodel,
119                 int in_x, int in_y, int in_w, int in_h, int in_rowspan,
120         int bg_color)
121 {
122         uint8_t *out_yp = 0, *out_up = 0, *out_vp = 0, *out_ap = 0;
123         uint8_t *in_yp = 0,  *in_up = 0,  *in_vp = 0,  *in_ap = 0;
124         if( BC_CModels::is_planar(in_colormodel) ) {
125                 in_yp = input_ptrs[0]; in_up = input_ptrs[1]; in_vp = input_ptrs[2];
126                 if( BC_CModels::has_alpha(in_colormodel) ) in_ap = input_ptrs[3];
127         }
128         if( BC_CModels::is_planar(out_colormodel) ) {
129                 out_yp = output_ptrs[0]; out_up = output_ptrs[1]; out_vp = output_ptrs[2];
130                 if( BC_CModels::has_alpha(out_colormodel) ) out_ap = output_ptrs[3];
131         }
132         init(output_ptrs, out_colormodel, out_x, out_y, out_w, out_h,
133                  out_yp, out_up, out_vp, out_ap, out_rowspan,
134              input_ptrs, in_colormodel, in_x, in_y, in_w, in_h,
135                  in_yp, in_up, in_vp, in_ap, in_rowspan,  bg_color);
136 }
137
138 BC_Xfer::~BC_Xfer()
139 {
140         delete [] column_table;
141         delete [] row_table;
142 }
143
144 void BC_CModels::transfer(unsigned char **output_rows, unsigned char **input_rows,
145         unsigned char *out_yp, unsigned char *out_up, unsigned char *out_vp,
146         unsigned char *in_yp, unsigned char *in_up, unsigned char *in_vp,
147         int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h,
148         int in_colormodel, int out_colormodel, int bg_color, int in_rowspan, int out_rowspan)
149 {
150         BC_Xfer xfer(output_rows, input_rows,
151                 out_yp, out_up, out_vp, in_yp, in_up, in_vp,
152                 in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h,
153                 in_colormodel, out_colormodel, bg_color, in_rowspan, out_rowspan);
154         xfer.xfer();
155 }
156
157 void BC_CModels::transfer(
158         uint8_t **output_ptrs, int out_colormodel,
159                 int out_x, int out_y, int out_w, int out_h, int out_rowspan,
160         uint8_t **input_ptrs, int in_colormodel,
161                 int in_x, int in_y, int in_w, int in_h, int in_rowspan,  int bg_color)
162 {
163         BC_Xfer xfer(
164                 output_ptrs, out_colormodel, out_x, out_y, out_w, out_h, out_rowspan,
165                 input_ptrs, in_colormodel, in_x, in_y, in_w, in_h, in_rowspan,  bg_color);
166         xfer.xfer();
167 }
168
169 // specialized functions
170
171 //  in bccmdl.py:  specialize("bc_rgba8888", "bc_transparency", "XFER_rgba8888_to_transparency")
172 void BC_Xfer::XFER_rgba8888_to_transparency(unsigned y0, unsigned y1)
173 {
174   for( unsigned i=y0; i<y1; ++i ) {
175     uint8_t *outp = output_rows[i + out_y] + out_x * out_pixelsize;
176     uint8_t *inp_row = input_rows[row_table[i]];
177     int bit_no = 0, bit_vec = 0;
178     for( unsigned j=0; j<out_w; ) {
179       uint8_t *inp = inp_row + column_table[j];
180       if( inp[3] < 127 ) bit_vec |= 0x01 << bit_no;
181       bit_no = ++j & 7;
182       if( !bit_no ) { *outp++ = bit_vec;  bit_vec = 0; }
183     }
184     if( bit_no ) *outp = bit_vec;
185   }
186 }
187
188 BC_Xfer::SlicerList BC_Xfer::slicers;
189
190 BC_Xfer::SlicerList::SlicerList()
191 {
192   count = 0;
193 }
194
195 BC_Xfer::SlicerList::~SlicerList()
196 {
197   reset();
198 }
199
200 void BC_Xfer::SlicerList::reset()
201 {
202   lock("BC_Xfer::SlicerList::reset");
203   while( last ) remove(last);
204   count = 0;
205   unlock();
206 }
207
208 BC_Xfer::Slicer *BC_Xfer::SlicerList::get_slicer(BC_Xfer *xp)
209 {
210   Slicer *slicer = first;
211   if( !slicer ) {
212     if( count < BC_Resources::machine_cpus ) {
213       slicer = new Slicer(xp);
214       ++count;
215     }
216   }
217   else
218     remove_pointer(slicer);
219   return slicer;
220 }
221
222 void BC_Xfer::xfer_slices(int slices)
223 {
224   if( !xfn ) return;
225   int max_slices = BC_Resources::machine_cpus/2;
226   if( slices > max_slices ) slices = max_slices;
227   if( slices < 1 ) slices = 1;
228   Slicer *active[slices];
229   unsigned y0 = 0, y1 = out_h;
230   int slices1 = slices-1;
231   if( slices1 > 0 ) {
232     slicers.lock("BC_Xfer::xfer_slices");
233     for( int i=0; i<slices1; y0=y1 ) {
234       Slicer *slicer = slicers.get_slicer(this);
235       if( !slicer ) { slices1 = i;  break; }
236       active[i] = slicer;
237       y1 = out_h * ++i / slices;
238       slicer->slice(this, y0, y1);
239     }
240     slicers.unlock();
241   }
242   (this->*xfn)(y0, out_h);
243   if( slices1 > 0 ) {
244     for( int i=0; i<slices1; ++i )
245       active[i]->complete->lock("BC_Xfer::xfer_slices");
246     slicers.lock("BC_Xfer::xfer_slices");
247     for( int i=0; i<slices1; ++i )
248       slicers.append(active[i]);
249     slicers.unlock();
250   }
251 }
252
253 BC_Xfer::Slicer::Slicer(BC_Xfer *xp)
254 {
255   this->xp = xp;
256   init = new Condition(0, "BC_Xfer::Slicer::init", 0);
257   complete = new Condition(0, "BC_Xfer::Slicer::complete", 0);
258   done = 0;
259   start();
260 }
261 BC_Xfer::Slicer::~Slicer()
262 {
263   done = 1;
264   init->unlock();
265   join();
266   delete complete;
267   delete init;
268 }
269
270 void BC_Xfer::Slicer::slice(BC_Xfer *xp, unsigned y0, unsigned y1)
271 {
272   this->xp = xp;
273   this->y0 = y0;
274   this->y1 = y1;
275   init->unlock();
276 }
277
278 void BC_Xfer::Slicer::run()
279 {
280   while( !done ) {
281     init->lock("Slicer::run");
282     if( done ) break;
283     xfer_fn xfn = xp->xfn;
284     (xp->*xfn)(y0, y1);
285     complete->unlock();
286   }
287 }
288
289 void BC_CModels::bcxfer_stop_slicers()
290 {
291   BC_Xfer::slicers.reset();
292 }
293