initial commit
[goodguy/history.git] / cinelerra-5.0 / 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 "format.inc"
28 #include "labels.h"
29 #include "mutex.h"
30 #include "mwindow.h"
31 #include "packagedispatcher.h"
32 #include "packagerenderer.h"
33 #include "preferences.h"
34 #include "render.h"
35
36
37
38
39 PackageDispatcher::PackageDispatcher()
40 {
41         packages = 0;
42         package_lock = new Mutex("PackageDispatcher::package_lock");
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         delete package_lock;
54 }
55
56 int PackageDispatcher::create_packages(MWindow *mwindow,
57         EDL *edl,
58         Preferences *preferences,
59         int strategy, 
60         Asset *default_asset, 
61         double total_start, 
62         double total_end,
63         int test_overwrite)
64 {
65         int result = 0;
66
67         this->mwindow = mwindow;
68         this->edl = edl;
69         this->preferences = preferences;
70         this->strategy = strategy;
71         this->default_asset = default_asset;
72         this->total_start = total_start;
73         this->total_end = total_end;
74
75         nodes = preferences->get_enabled_nodes();
76         audio_position = Units::to_int64(total_start * default_asset->sample_rate);
77         video_position = Units::to_int64(total_start * default_asset->frame_rate);
78         audio_end = Units::to_int64(total_end * default_asset->sample_rate);
79         video_end = Units::to_int64(total_end * default_asset->frame_rate);
80         current_package = 0;
81
82 // sleep(1);
83 // printf("PackageDispatcher::create_packages 1 %d %f %f\n", 
84 // video_end, 
85 // total_end, 
86 // default_asset->frame_rate);
87
88
89
90         if(strategy == SINGLE_PASS)
91         {
92                 total_len = this->total_end - this->total_start;
93                 package_len = total_len;
94                 min_package_len = total_len;
95                 total_packages = 1;
96                 total_allocated = 1;
97                 packages = new RenderPackage*[total_allocated];
98                 packages[0] = new RenderPackage;
99                 packages[0]->audio_start = audio_position;
100                 packages[0]->audio_end = audio_end;
101                 packages[0]->video_start = video_position;
102                 packages[0]->video_end = video_end;
103                 strcpy(packages[0]->path, default_asset->path);
104         }
105         else
106         if(strategy == SINGLE_PASS_FARM)
107         {
108                 total_len = this->total_end - this->total_start;
109                 total_packages = preferences->renderfarm_job_count;
110                 total_allocated = total_packages + nodes;
111                 packages = new RenderPackage*[total_allocated];
112                 package_len = total_len / total_packages;
113                 min_package_len = 2.0 / edl->session->frame_rate;
114
115
116 //printf("PackageDispatcher::create_packages: %f / %d = %f\n", total_len, total_packages, package_len);
117                 Render::get_starting_number(default_asset->path, 
118                         current_number,
119                         number_start, 
120                         total_digits,
121                         3);
122
123                 for(int i = 0; i < total_allocated; i++)
124                 {
125                         RenderPackage *package = packages[i] = new RenderPackage;
126
127 // Create file number differently if image file sequence
128                         Render::create_filename(package->path, 
129                                 default_asset->path, 
130                                 current_number,
131                                 total_digits,
132                                 number_start);
133                         current_number++;
134                 }
135         }
136         else
137         if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
138         {
139                 Label *label = edl->labels->first;
140                 total_packages = 0;
141                 packages = new RenderPackage*[edl->labels->total() + 2];
142
143                 Render::get_starting_number(default_asset->path, 
144                         current_number,
145                         number_start, 
146                         total_digits,
147                         2);
148
149                 while(audio_position < audio_end)
150                 {
151                         RenderPackage *package = 
152                                 packages[total_packages] = 
153                                 new RenderPackage;
154                         package->audio_start = audio_position;
155                         package->video_start = video_position;
156
157
158                         while(label && 
159                                 (label->position < (double)audio_position / default_asset->sample_rate ||
160                                 EQUIV(label->position, (double)audio_position / default_asset->sample_rate)))
161                         {
162                                 label = label->next;
163                         }
164
165                         if(!label)
166                         {
167                                 package->audio_end = Units::to_int64(total_end * default_asset->sample_rate);
168                                 package->video_end = Units::to_int64(total_end * default_asset->frame_rate);
169                         }
170                         else
171                         {
172                                 package->audio_end = Units::to_int64(label->position * default_asset->sample_rate);
173                                 package->video_end = Units::to_int64(label->position * default_asset->frame_rate);
174                         }
175
176                         if(package->audio_end > audio_end)
177                         {
178                                 package->audio_end = audio_end;
179                         }
180
181                         if(package->video_end > video_end)
182                         {
183                                 package->video_end = video_end;
184                         }
185
186                         audio_position = package->audio_end;
187                         video_position = package->video_end;
188 // Create file number differently if image file sequence
189                         Render::create_filename(package->path, 
190                                 default_asset->path, 
191                                 current_number,
192                                 total_digits,
193                                 number_start);
194                         current_number++;
195
196                         total_packages++;
197                 }
198                 
199                 total_allocated = total_packages;
200         }
201         else
202         if(strategy == BRENDER_FARM)
203         {
204                 total_len = this->total_end - this->total_start;
205
206 // Create packages as they're requested.
207                 total_packages = 0;
208                 total_allocated = 0;
209                 packages = 0;
210
211                 Render::get_starting_number(default_asset->path, 
212                         current_number,
213                         number_start, 
214                         total_digits,
215                         6);
216
217 // Master node only
218                 if(preferences->renderfarm_nodes.total == 1)
219                 {
220                         package_len = total_len;
221                         min_package_len = total_len;
222                 }
223                 else
224                 {
225                         package_len = preferences->brender_fragment / 
226                                 edl->session->frame_rate;
227                         min_package_len = 1.0 / edl->session->frame_rate;
228                 }
229         }
230
231 // Test existence of every output file.
232 // Only if this isn't a background render or non interactive.
233         if(strategy != BRENDER_FARM && 
234                 test_overwrite &&
235                 mwindow)
236         {
237                 ArrayList<char*> paths;
238                 for(int i = 0; i < total_allocated; i++)
239                 {
240                         paths.append(packages[i]->path);
241                 }
242                 result = ConfirmSave::test_files(mwindow, &paths);
243         }
244         
245         return result;
246 }
247
248 RenderPackage* PackageDispatcher::get_package(double frames_per_second, 
249         int client_number,
250         int use_local_rate)
251 {
252         const int debug = 0;
253         package_lock->lock("PackageDispatcher::get_package");
254
255         if(debug) printf("PackageDispatcher::get_package %d %f %d %d\n", 
256                 __LINE__,
257                 frames_per_second,
258                 client_number,
259                 use_local_rate);
260
261 // Store new frames per second for the node
262         if(!EQUIV(frames_per_second, 0))
263         {
264                 preferences->set_rate(frames_per_second, client_number);
265                 if(mwindow) mwindow->preferences->copy_rates_from(preferences);
266         }
267         else
268 // Use previous frames per second
269         {
270                 frames_per_second = preferences->get_rate(client_number);
271         }
272
273         if(debug) printf("PackageDispatcher::get_package %d %f %d %d\n", 
274                 __LINE__,
275                 frames_per_second,
276                 client_number,
277                 use_local_rate);
278
279         float avg_frames_per_second = preferences->get_avg_rate(use_local_rate);
280
281         RenderPackage *result = 0;
282 //printf("PackageDispatcher::get_package 1 %d\n", strategy);
283         if(strategy == SINGLE_PASS || 
284                 strategy == FILE_PER_LABEL || 
285                 strategy == FILE_PER_LABEL_FARM)
286         {
287                 if(current_package < total_packages)
288                 {
289                         result = packages[current_package];
290                         current_package++;
291                 }
292         }
293         else
294         if(strategy == SINGLE_PASS_FARM)
295         {
296
297 //printf("PackageDispatcher::get_package %ld %ld %ld %ld\n", audio_position, video_position, audio_end, video_end);
298
299                 if(audio_position < audio_end ||
300                         video_position < video_end)
301                 {
302 // Last package
303                         double scaled_len;
304                         result = packages[current_package];
305                         result->audio_start = audio_position;
306                         result->video_start = video_position;
307
308                         if(current_package >= total_allocated - 1)
309                         {
310                                 result->audio_end = audio_end;
311                                 result->video_end = video_end;
312                                 audio_position = result->audio_end;
313                                 video_position = result->video_end;
314                         }
315                         else
316 // No useful speed data.  May get infinity for real fast jobs.
317                         if(frames_per_second > 0x7fffff || frames_per_second < 0 ||
318                                 EQUIV(frames_per_second, 0) || 
319                                 EQUIV(avg_frames_per_second, 0))
320                         {
321                                 scaled_len = MAX(package_len, min_package_len);
322
323                                 result->audio_end = audio_position + 
324                                         Units::round(scaled_len * default_asset->sample_rate);
325                                 result->video_end = video_position + 
326                                         Units::round(scaled_len * default_asset->frame_rate);
327
328 // If we get here without any useful speed data, render the whole thing.
329                                 if(current_package >= total_packages - 1)
330                                 {
331                                         result->audio_end = audio_end;
332                                         result->video_end = video_end;
333                                 }
334                                 else
335                                 {
336                                         result->audio_end = MIN(audio_end, result->audio_end);
337                                         result->video_end = MIN(video_end, result->video_end);
338                                 }
339
340                                 audio_position = result->audio_end;
341                                 video_position = result->video_end;
342                         }
343                         else
344 // Useful speed data and future packages exist.  Scale the 
345 // package size to fit the requestor.
346                         {
347                                 scaled_len = package_len * 
348                                         frames_per_second / 
349                                         avg_frames_per_second;
350                                 scaled_len = MAX(scaled_len, min_package_len);
351
352                                 result->audio_end = result->audio_start + 
353                                         Units::to_int64(scaled_len * default_asset->sample_rate);
354                                 result->video_end = result->video_start +
355                                         Units::to_int64(scaled_len * default_asset->frame_rate);
356
357                                 result->audio_end = MIN(audio_end, result->audio_end);
358                                 result->video_end = MIN(video_end, result->video_end);
359
360                                 audio_position = result->audio_end;
361                                 video_position = result->video_end;
362
363 // Package size is no longer touched between total_packages and total_allocated
364                                 if(current_package < total_packages - 1)
365                                 {
366                                         package_len = (double)(audio_end - audio_position) / 
367                                                 (double)default_asset->sample_rate /
368                                                 (double)(total_packages - current_package);
369                                 }
370
371                         }
372
373                         current_package++;
374 //printf("Dispatcher::get_package 50  %d " _LD " " _LD " " _LD " " _LD "\n", 
375 // __LINE__,
376 // result->audio_start, 
377 // result->video_start, 
378 // result->audio_end, 
379 // result->video_end);
380                 }
381         }
382         else
383         if(strategy == BRENDER_FARM)
384         {
385 //printf("Dispatcher::get_package 1 %d %d\n", video_position, video_end);
386                 if(video_position < video_end)
387                 {
388 // Allocate new packages
389                         if(total_packages == 0)
390                         {
391                                 total_allocated = 256;
392                                 packages = new RenderPackage*[total_allocated];
393                         }
394                         else
395                         if(total_packages >= total_allocated)
396                         {
397                                 RenderPackage **old_packages = packages;
398                                 total_allocated *= 2;
399                                 packages = new RenderPackage*[total_allocated];
400                                 memcpy(packages, 
401                                         old_packages, 
402                                         total_packages * sizeof(RenderPackage*));
403                                 delete [] old_packages;
404                         }
405
406 // Calculate package.
407                         result = packages[total_packages] = new RenderPackage;
408                         double scaled_len;
409
410 // No load balancing data exists
411                         if(EQUIV(frames_per_second, 0) || 
412                                 EQUIV(avg_frames_per_second, 0))
413                         {
414                                 scaled_len = package_len;
415                         }
416                         else
417 // Load balancing data exists
418                         {
419                                 scaled_len = package_len * 
420                                         frames_per_second / 
421                                         avg_frames_per_second;
422                         }
423
424                         scaled_len = MAX(scaled_len, min_package_len);
425
426 // Always an image file sequence
427                         result->audio_start = audio_position;
428                         result->video_start = video_position;
429                         result->audio_end = result->audio_start + 
430                                 Units::to_int64(scaled_len * default_asset->sample_rate);
431                         result->video_end = result->video_start + 
432                                 Units::to_int64(scaled_len * default_asset->frame_rate);
433                         if(result->video_end == result->video_start) result->video_end++;
434                         audio_position = result->audio_end;
435                         video_position = result->video_end;
436 // The frame numbers are read from the vframe objects themselves.
437                         Render::create_filename(result->path,
438                                 default_asset->path,
439                                 0,
440                                 total_digits,
441                                 number_start);
442 //printf("PackageDispatcher::get_package 2 %s\n", result->path);
443
444                         current_number++;
445                         total_packages++;
446                         current_package++;
447                 }
448         }
449
450         package_lock->unlock();
451
452         if(debug && result) printf("PackageDispatcher::get_package %d %ld\n", __LINE__, (long)(result->video_end - result->video_start));
453         return result;
454 }
455
456
457 ArrayList<Indexable*>* PackageDispatcher::get_asset_list()
458 {
459         ArrayList<Indexable*> *assets = new ArrayList<Indexable*>;
460
461 const int debug = 0;
462 if(debug) printf("PackageDispatcher::get_asset_list %d\n", __LINE__);
463 if(debug) default_asset->dump();
464         for(int i = 0; i < current_package; i++)
465         {
466                 Asset *asset = new Asset;
467                 asset->copy_from(default_asset, 1);
468                 strcpy(asset->path, packages[i]->path);
469                 asset->video_length = packages[i]->video_end - packages[i]->video_start;
470                 asset->audio_length = packages[i]->audio_end - packages[i]->audio_start;
471                 assets->append(asset);
472 if(debug) printf("PackageDispatcher::get_asset_list %d\n", __LINE__);
473 if(debug) asset->dump();
474         }
475
476         return assets;
477 }
478
479 RenderPackage* PackageDispatcher::get_package(int number)
480 {
481         return packages[number];
482 }
483
484 int PackageDispatcher::get_total_packages()
485 {
486         return total_allocated;
487 }
488