exec bits, desktop icon props, noexecstack, attach transitions to selected edits...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / packagedispatcher.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 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 #include "asset.h"
23 #include "clip.h"
24 #include "confirmsave.h"
25 #include "edl.h"
26 #include "edlsession.h"
27 #include "labels.h"
28 #include "mutex.h"
29 #include "mwindow.h"
30 #include "packagedispatcher.h"
31 #include "packagerenderer.h"
32 #include "preferences.h"
33 #include "render.h"
34 #include "file.h"
35
36
37
38 PackageDispatcher::PackageDispatcher()
39 {
40         packages = 0;
41         package_lock = new Mutex("PackageDispatcher::package_lock");
42         packaging_engine = 0;
43 }
44
45 PackageDispatcher::~PackageDispatcher()
46 {
47         if(packages)
48         {
49                 for(int i = 0; i < total_packages; i++)
50                         delete packages[i];
51                 delete [] packages;
52         }
53         if (packaging_engine)
54                 delete packaging_engine;
55         delete package_lock;
56 }
57
58 int PackageDispatcher::create_packages(MWindow *mwindow,
59         EDL *edl,
60         Preferences *preferences,
61         int strategy,
62         Asset *default_asset,
63         double total_start,
64         double total_end,
65         int test_overwrite)
66 {
67         int result = 0;
68
69         this->mwindow = mwindow;
70         this->edl = edl;
71         this->preferences = preferences;
72         this->strategy = strategy;
73         this->default_asset = default_asset;
74         this->total_start = total_start;
75         this->total_end = total_end;
76
77         nodes = preferences->get_enabled_nodes();
78         audio_position = Units::to_int64(total_start * default_asset->sample_rate);
79         video_position = Units::to_int64(total_start * default_asset->frame_rate);
80         audio_end = Units::to_int64(total_end * default_asset->sample_rate);
81         video_end = Units::to_int64(total_end * default_asset->frame_rate);
82         current_package = 0;
83
84 // sleep(1);
85 // printf("PackageDispatcher::create_packages 1 %d %f %f\n",
86 // video_end,
87 // total_end,
88 // default_asset->frame_rate);
89
90
91
92         if(strategy == SINGLE_PASS)
93         {
94                 total_len = this->total_end - this->total_start;
95                 package_len = total_len;
96                 min_package_len = total_len;
97                 total_packages = 1;
98                 total_allocated = 1;
99                 packages = new RenderPackage*[total_allocated];
100                 packages[0] = new RenderPackage;
101                 packages[0]->audio_start = audio_position;
102                 packages[0]->audio_end = audio_end;
103                 packages[0]->video_start = video_position;
104                 packages[0]->video_end = video_end;
105                 packages[0]->audio_do = default_asset->audio_data;
106                 packages[0]->video_do = default_asset->video_data;
107                 strcpy(packages[0]->path, default_asset->path);
108         }
109         else
110         if(strategy == SINGLE_PASS_FARM)
111         {
112                 packaging_engine = File::new_packaging_engine(default_asset);
113                 packaging_engine->create_packages_single_farm(
114                                         edl,
115                                         preferences,
116                                         default_asset,
117                                         total_start,
118                                         total_end);
119         }
120         else
121         if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
122         {
123                 Label *label = edl->labels->first;
124                 total_packages = 0;
125                 packages = new RenderPackage*[edl->labels->total() + 2];
126
127                 Render::get_starting_number(default_asset->path,
128                         current_number,
129                         number_start,
130                         total_digits,
131                         2);
132
133                 while(audio_position < audio_end)
134                 {
135                         RenderPackage *package =
136                                 packages[total_packages] =
137                                 new RenderPackage;
138                         package->audio_start = audio_position;
139                         package->video_start = video_position;
140                         package->audio_do = default_asset->audio_data;
141                         package->video_do = default_asset->video_data;
142
143
144                         while(label &&
145                                 (label->position < (double)audio_position / default_asset->sample_rate ||
146                                 EQUIV(label->position, (double)audio_position / default_asset->sample_rate)))
147                         {
148                                 label = label->next;
149                         }
150
151                         if(!label)
152                         {
153                                 package->audio_end = Units::to_int64(total_end * default_asset->sample_rate);
154                                 package->video_end = Units::to_int64(total_end * default_asset->frame_rate);
155                         }
156                         else
157                         {
158                                 package->audio_end = Units::to_int64(label->position * default_asset->sample_rate);
159                                 package->video_end = Units::to_int64(label->position * default_asset->frame_rate);
160                         }
161
162                         if(package->audio_end > audio_end)
163                         {
164                                 package->audio_end = audio_end;
165                         }
166
167                         if(package->video_end > video_end)
168                         {
169                                 package->video_end = video_end;
170                         }
171
172                         audio_position = package->audio_end;
173                         video_position = package->video_end;
174 // Create file number differently if image file sequence
175                         Render::create_filename(package->path,
176                                 default_asset->path,
177                                 current_number,
178                                 total_digits,
179                                 number_start);
180                         current_number++;
181
182                         total_packages++;
183                 }
184
185                 total_allocated = total_packages;
186         }
187         else
188         if(strategy == BRENDER_FARM)
189         {
190                 total_len = this->total_end - this->total_start;
191
192 // Create packages as they're requested.
193                 total_packages = 0;
194                 total_allocated = 0;
195                 packages = 0;
196
197                 Render::get_starting_number(default_asset->path,
198                         current_number,
199                         number_start,
200                         total_digits,
201                         6);
202
203 // Master node only
204                 if(preferences->renderfarm_nodes.total == 1)
205                 {
206                         package_len = total_len;
207                         min_package_len = total_len;
208                 }
209                 else
210                 {
211                         package_len = preferences->brender_fragment /
212                                 edl->session->frame_rate;
213                         min_package_len = 1.0 / edl->session->frame_rate;
214                 }
215         }
216
217 // Test existence of every output file.
218 // Only if this isn't a background render or non interactive.
219         if(strategy != BRENDER_FARM &&
220                 test_overwrite &&
221                 mwindow)
222         {
223                 ArrayList<char*> paths;
224                 get_package_paths(&paths);
225                 result = ConfirmSave::test_files(mwindow, &paths);
226                 paths.remove_all_objects();
227         }
228
229         return result;
230 }
231
232 void PackageDispatcher::get_package_paths(ArrayList<char*> *path_list)
233 {
234                 if (strategy == SINGLE_PASS_FARM)
235                         packaging_engine->get_package_paths(path_list);
236                 else
237                 {
238                         for(int i = 0; i < total_allocated; i++)
239                                 path_list->append(strdup(packages[i]->path));
240                         path_list->set_free();
241                 }
242
243 }
244
245 RenderPackage* PackageDispatcher::get_package(double frames_per_second,
246         int client_number,
247         int use_local_rate)
248 {
249         const int debug = 0;
250         package_lock->lock("PackageDispatcher::get_package");
251
252         if(debug) printf("PackageDispatcher::get_package %d %f %d %d\n",
253                 __LINE__,
254                 frames_per_second,
255                 client_number,
256                 use_local_rate);
257
258 // Store new frames per second for the node
259         if(!EQUIV(frames_per_second, 0))
260         {
261                 preferences->set_rate(frames_per_second, client_number);
262                 if(mwindow) mwindow->preferences->copy_rates_from(preferences);
263         }
264         else
265 // Use previous frames per second
266         {
267                 frames_per_second = preferences->get_rate(client_number);
268         }
269
270         if(debug) printf("PackageDispatcher::get_package %d %f %d %d\n",
271                 __LINE__,
272                 frames_per_second,
273                 client_number,
274                 use_local_rate);
275
276         float avg_frames_per_second = preferences->get_avg_rate(use_local_rate);
277
278         RenderPackage *result = 0;
279 //printf("PackageDispatcher::get_package 1 %d\n", strategy);
280         if(strategy == SINGLE_PASS ||
281                 strategy == FILE_PER_LABEL ||
282                 strategy == FILE_PER_LABEL_FARM)
283         {
284                 if(current_package < total_packages)
285                 {
286                         result = packages[current_package];
287                         current_package++;
288                 }
289         }
290         else
291         if(strategy == SINGLE_PASS_FARM)
292         {
293                 result = packaging_engine->get_package_single_farm(frames_per_second,
294                                                 client_number,
295                                                 use_local_rate);
296         }
297         else
298         if(strategy == BRENDER_FARM)
299         {
300 //printf("Dispatcher::get_package 1 %d %d\n", video_position, video_end);
301                 if(video_position < video_end)
302                 {
303 // Allocate new packages
304                         if(total_packages == 0)
305                         {
306                                 total_allocated = 256;
307                                 packages = new RenderPackage*[total_allocated];
308                         }
309                         else
310                         if(total_packages >= total_allocated)
311                         {
312                                 RenderPackage **old_packages = packages;
313                                 total_allocated *= 2;
314                                 packages = new RenderPackage*[total_allocated];
315                                 memcpy(packages,
316                                         old_packages,
317                                         total_packages * sizeof(RenderPackage*));
318                                 delete [] old_packages;
319                         }
320
321 // Calculate package.
322                         result = packages[total_packages] = new RenderPackage;
323                         double scaled_len;
324
325 // No load balancing data exists
326                         if(EQUIV(frames_per_second, 0) ||
327                                 EQUIV(avg_frames_per_second, 0))
328                         {
329                                 scaled_len = package_len;
330                         }
331                         else
332 // Load balancing data exists
333                         {
334                                 scaled_len = package_len *
335                                         frames_per_second /
336                                         avg_frames_per_second;
337                         }
338
339                         scaled_len = MAX(scaled_len, min_package_len);
340
341 // Always an image file sequence
342                         result->audio_start = audio_position;
343                         result->video_start = video_position;
344                         result->audio_end = result->audio_start +
345                                 Units::to_int64(scaled_len * default_asset->sample_rate);
346                         result->video_end = result->video_start +
347                                 Units::to_int64(scaled_len * default_asset->frame_rate);
348                         if(result->video_end == result->video_start) result->video_end++;
349                         audio_position = result->audio_end;
350                         video_position = result->video_end;
351                         result->audio_do = default_asset->audio_data;
352                         result->video_do = default_asset->video_data;
353
354
355 // The frame numbers are read from the vframe objects themselves.
356                         Render::create_filename(result->path,
357                                 default_asset->path,
358                                 0,
359                                 total_digits,
360                                 number_start);
361 //printf("PackageDispatcher::get_package 2 %s\n", result->path);
362
363                         current_number++;
364                         total_packages++;
365                         current_package++;
366                 }
367         }
368
369         package_lock->unlock();
370
371         if(debug && result) printf("PackageDispatcher::get_package %d %ld\n", __LINE__, (long)(result->video_end - result->video_start));
372         return result;
373 }
374
375
376 ArrayList<Indexable*>* PackageDispatcher::get_asset_list()
377 {
378         ArrayList<Indexable*> *assets = new ArrayList<Indexable*>;
379
380 const int debug = 0;
381 if(debug) printf("PackageDispatcher::get_asset_list %d\n", __LINE__);
382 if(debug) default_asset->dump();
383         for(int i = 0; i < current_package; i++)
384         {
385                 Asset *asset = new Asset;
386                 asset->copy_from(default_asset, 1);
387                 strcpy(asset->path, packages[i]->path);
388                 asset->video_length = packages[i]->video_end - packages[i]->video_start;
389                 asset->audio_length = packages[i]->audio_end - packages[i]->audio_start;
390                 assets->append(asset);
391 if(debug) printf("PackageDispatcher::get_asset_list %d\n", __LINE__);
392 if(debug) asset->dump();
393         }
394
395         return assets;
396 }
397
398 int64_t PackageDispatcher::get_progress_max()
399 {
400         if (strategy == SINGLE_PASS_FARM)
401                 return packaging_engine->get_progress_max();
402         else
403                 return Units::to_int64(default_asset->sample_rate *
404                                 (total_end - total_start)) +
405                         Units::to_int64(preferences->render_preroll *
406                                 total_allocated *
407                                 default_asset->sample_rate);
408 }
409
410 int PackageDispatcher::get_total_packages()
411 {
412         return total_allocated;
413 }
414
415 int PackageDispatcher::packages_are_done()
416 {
417         if (packaging_engine)
418                 return packaging_engine->packages_are_done();
419         return 0;
420 }