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