r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / render.C
blobed802e3b8ade8cce40057f21c571ac5419da286a
1 #include "arender.h"
2 #include "assets.h"
3 #include "auto.h"
4 #include "bcprogressbox.h"
5 #include "cache.h"
6 #include "clip.h"
7 #include "compresspopup.h"
8 #include "cwindow.h"
9 #include "cwindowgui.h"
10 #include "defaults.h"
11 #include "edits.h"
12 #include "edl.h"
13 #include "edlsession.h"
14 #include "errorbox.h"
15 #include "file.h"
16 #include "filesystem.h"
17 #include "formatcheck.h"
18 #include "formatpopup.h"
19 #include "formattools.h"
20 #include "labels.h"
21 #include "loadmode.h"
22 #include "localsession.h"
23 #include "mainprogress.h"
24 #include "mainsession.h"
25 #include "mainundo.h"
26 #include "mwindow.h"
27 #include "mwindowgui.h"
28 #include "module.h"
29 #include "mutex.h"
30 #include "neworappend.h"
31 #include "packagedispatcher.h"
32 #include "packagerenderer.h"
33 #include "patchbay.h"
34 #include "playabletracks.h"
35 #include "preferences.h"
36 #include "statusbar.h"
37 #include "timebar.h"
38 #include "tracks.h"
39 #include "transportque.h"
40 #include "quicktime.h"
41 #include "vrender.h"
42 #include "render.h"
43 #include "renderfarm.h"
44 #include "vedit.h"
45 #include "vframe.h"
46 #include "videoconfig.h"
48 #include <ctype.h>
49 #include <string.h>
51 #include <libintl.h>
52 #define _(String) gettext(String)
53 #define gettext_noop(String) String
54 #define N_(String) gettext_noop (String)
58 RenderItem::RenderItem(MWindow *mwindow)
59  : BC_MenuItem(_("Render..."), "Shift+R", 'R')
61         this->mwindow = mwindow;
62         set_shift(1);
65 int RenderItem::handle_event() 
67         mwindow->render_single();
68         return 1;
80 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
81  : Thread()
83         this->mwindow = mwindow;
84         this->render = render;
85         last_value = 0;
86         Thread::set_synchronous(1);
89 RenderProgress::~RenderProgress()
91         Thread::cancel();
92         Thread::join();
96 void RenderProgress::run()
98         Thread::disable_cancel();
99         while(1)
100         {
101                 if(render->total_rendered != last_value)
102                 {
103                         render->progress->update(render->total_rendered);
104                         last_value = render->total_rendered;
105                 }
107                 Thread::enable_cancel();
108                 sleep(1);
109                 Thread::disable_cancel();
110         }
122 MainPackageRenderer::MainPackageRenderer(Render *render)
123  : PackageRenderer()
125         this->render = render;
130 MainPackageRenderer::~MainPackageRenderer()
135 int MainPackageRenderer::get_result()
137         return render->result;
140 void MainPackageRenderer::set_result(int value)
142         if(value)
143                 render->result = value;
146 void MainPackageRenderer::set_progress(int64_t value)
148         render->counter_lock->lock();
149         render->total_rendered += audio_read_length;
150         render->counter_lock->unlock();
153 int MainPackageRenderer::progress_cancelled()
155         return render->progress->is_cancelled();
164 Render::Render(MWindow *mwindow)
165  : Thread()
167         this->mwindow = mwindow;
168         in_progress = 0;
169         package_lock = new Mutex;
170         counter_lock = new Mutex;
173 Render::~Render()
175         delete package_lock;
176         delete counter_lock;
180 int Render::check_asset(EDL *edl, Asset &asset)
182         if(asset.video_data && 
183                 edl->tracks->playable_video_tracks() &&
184                 File::supports_video(asset.format))
185         {
186                 asset.video_data = 1;
187                 asset.layers = 1;
188                 asset.width = edl->session->output_w;
189                 asset.height = edl->session->output_h;
190         }
191         else
192         {
193                 asset.video_data = 0;
194                 asset.layers = 0;
195         }
197         if(asset.audio_data && 
198                 edl->tracks->playable_audio_tracks() &&
199                 File::supports_audio(asset.format))
200         {
201                 asset.audio_data = 1;
202                 asset.channels = edl->session->audio_channels;
203                 if(asset.format == FILE_MOV) asset.byte_order = 0;
204         }
205         else
206         {
207                 asset.audio_data = 0;
208                 asset.channels = 0;
209         }
210 //printf("Render::check_asset 3\n");
214 void Render::start_progress()
216         char filename[BCTEXTLEN];
217         char string[BCTEXTLEN];
218         FileSystem fs;
219 // Generate the progress box
220         fs.extract_name(filename, default_asset->path);
221         sprintf(string, _("Rendering %s..."), filename);
223 // Don't bother with the filename since renderfarm defeats the meaning
224         progress = mwindow->mainprogress->start_progress(_("Rendering..."), 
225                 Units::to_int64(default_asset->sample_rate * 
226                         (total_end - total_start)) +
227                 Units::to_int64(preferences->render_preroll * 
228                         packages->total_allocated * 
229                         default_asset->sample_rate));
230         render_progress = new RenderProgress(mwindow, this);
231         render_progress->start();
234 void Render::stop_progress()
236         if(progress)
237         {
238                 char string[BCTEXTLEN], string2[BCTEXTLEN];
239                 delete render_progress;
240                 progress->get_time(string);
241                 progress->stop_progress();
242                 delete progress;
244                 sprintf(string2, _("Rendering took %s"), string);
245                 mwindow->gui->lock_window();
246                 mwindow->gui->show_message(string2, BLACK);
247                 mwindow->gui->unlock_window();
248         }
249         progress = 0;
253 void Render::run()
255         int format_error;
256         char string[BCTEXTLEN];
257 // Total length in seconds
258         double total_length;
259         int last_audio_buffer;
260         RenderFarmServer *farm_server = 0;
261         FileSystem fs;
262         int total_digits;       // Total number of digits including padding the user specified.
263         int number_start;       // Character in the filename path at which the number begins
264         int current_number;    // The number the being injected into the filename.
265 // Pointer from file
266 // (VFrame*)(VFrame array [])(Channel [])
267         VFrame ***video_output;
268 // Pointer to output buffers
269         VFrame *video_output_ptr[MAX_CHANNELS];
270         double *audio_output_ptr[MAX_CHANNELS];
271         int done = 0;
274         progress = 0;
275         result = 0;
277 // Fix the EDL for rendering
278         default_asset = new Asset;
279         preferences = new Preferences;
280         *preferences = *mwindow->preferences;
281         command = new TransportCommand;
282         command->command = NORMAL_FWD;
283         *command->get_edl() = *mwindow->edl;
284         command->change_type = CHANGE_ALL;
285         command->set_playback_range(mwindow->edl);
289 // Adjust playback range with in/out points
290         if(mwindow->edl->local_session->in_point >= 0 ||
291                 mwindow->edl->local_session->out_point >= 0)
292         {
293                 if(mwindow->edl->local_session->in_point >= 0)
294                         command->start_position = mwindow->edl->local_session->in_point;
295                 else
296                         command->start_position = 0;
298                 if(mwindow->edl->local_session->out_point >= 0)
299                         command->end_position = mwindow->edl->local_session->out_point;
300                 else
301                         command->end_position = mwindow->edl->tracks->total_playable_length();
302         }
305         packages = new PackageDispatcher;
308 // Configure preview monitor
309         VideoOutConfig vconfig(PLAYBACK_LOCALHOST, 0);
310         PlaybackConfig *playback_config = new PlaybackConfig(PLAYBACK_LOCALHOST, 0);
311         for(int i = 0; i < MAX_CHANNELS; i++)
312         {
313                 vconfig.do_channel[i] = (i < command->get_edl()->session->video_channels);
314                 playback_config->vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
315                 playback_config->aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
316         }
318 // Create caches
319         audio_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
320         video_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
322         load_defaults(default_asset);
326         default_asset->frame_rate = command->get_edl()->session->frame_rate;
327         default_asset->sample_rate = command->get_edl()->session->sample_rate;
328         check_asset(command->get_edl(), *default_asset);
339 // Get format from user
340         do
341         {
342                 format_error = 0;
343                 result = 0;
345                 {
346                         RenderWindow window(mwindow, this, default_asset);
347                         window.create_objects();
348                         result = window.run_window();
349                 }
351                 if(!result)
352                 {
353 // Check the asset format for errors.
354                         FormatCheck format_check(default_asset);
355                         format_error = format_check.check_format();
356                 }
357         }while(format_error && !result);
359         check_asset(command->get_edl(), *default_asset);
360 //printf("%d %d\n", default_asset->video_data, default_asset->audio_data);
361         save_defaults(default_asset);
362         mwindow->save_defaults();
364 //printf("Render 2\n");
365 //default_asset->dump();
366         if(!result)
367         {
368 // Get total range to render
369                 total_start = command->start_position;
370                 total_end = command->end_position;
371                 total_length = total_end - total_start;
373 // Nothing to render
374                 if(EQUIV(total_length, 0))
375                 {
376                         result = 1;
377                 }
378         }
384 //printf("Render 3\n");
390 // Generate packages
391         if(!result)
392         {
393 // Stop background rendering
394                 mwindow->stop_brender();
396                 fs.complete_path(default_asset->path);
397                 if(preferences->use_renderfarm)
398                 {
399                         if(strategy == SINGLE_PASS)
400                                 strategy = SINGLE_PASS_FARM;
401                         else
402                         if(strategy == FILE_PER_LABEL)
403                                 strategy = FILE_PER_LABEL_FARM;
404                 }
405                 else
406                 {
407                         if(strategy == SINGLE_PASS_FARM)
408                                 strategy = SINGLE_PASS;
409                         else
410                         if(strategy == FILE_PER_LABEL_FARM)
411                                 strategy = FILE_PER_LABEL;
412                 }
414                 result = packages->create_packages(mwindow,
415                         command->get_edl(),
416                         preferences,
417                         strategy, 
418                         default_asset, 
419                         total_start, 
420                         total_end);
421         }
425 //printf("Render 4\n");
433         done = 0;
434         total_rendered = 0;
435         frames_per_second = 0;
437         if(!result)
438         {
439 // Start dispatching external jobs
440                 mwindow->gui->lock_window();
441                 mwindow->gui->show_message(_("Starting render farm"), BLACK);
442                 mwindow->gui->unlock_window();
443                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
444                 {
445                         farm_server = new RenderFarmServer(mwindow, 
446                                 packages,
447                                 preferences, 
448                                 1,
449                                 &result,
450                                 &total_rendered,
451                                 counter_lock,
452                                 default_asset,
453                                 command->get_edl(),
454                                 0);
455                         result = farm_server->start_clients();
456                         
457                         if(result)
458                         {
459                                 mwindow->gui->lock_window();
460                                 mwindow->gui->show_message(_("Failed to start render farm"), BLACK);
461                                 mwindow->gui->unlock_window();
462                         }
463                 }
464         }
467 //printf("Render 5\n");
470 // Perform local rendering
473         if(!result)
474         {
475                 start_progress();
476         
477         
480 //printf("Render 6\n");
481                 MainPackageRenderer package_renderer(this);
482 //printf("Render 7\n");
483                 package_renderer.initialize(mwindow,
484                                 command->get_edl(),   // Copy of master EDL
485                                 preferences, 
486                                 default_asset,
487                                 mwindow->plugindb);
490 //printf("Render 8\n");
496                 while(!result)
497                 {
498 // Get unfinished job
499                         RenderPackage *package;
501                         if(strategy == SINGLE_PASS_FARM)
502                         {
503 //printf("Render 9\n");
504                                 package = packages->get_package(frames_per_second, -1, 1);
505 //printf("Render 10\n");
506                         }
507                         else
508                         {
509                                 package = packages->get_package(0, -1, 1);
510                         }
512 // Exit point
513                         if(!package) 
514                         {
515                                 done = 1;
516                                 break;
517                         }
520 //printf("Render 11\n");
522                         Timer timer;
523                         timer.update();
525                         if(package_renderer.render_package(package))
526                                 result = 1;
527 // Result is also set directly by the RenderFarm.
528 //printf("Render 12\n");
530                         frames_per_second = (double)(package->video_end - package->video_start) / 
531                                 (double)(timer.get_difference() / 1000);
533 //printf("Render 13\n");
535                 } // file_number
537 //printf("Render::run: Session finished.\n");
543                 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
544                 {
545                         farm_server->wait_clients();
546                 }
549 // Notify of error
550                 if(result && 
551                         !progress->is_cancelled())
552                 {
553                         ErrorBox error_box(PROGRAM_NAME ": Error",
554                                 mwindow->gui->get_abs_cursor_x(),
555                                 mwindow->gui->get_abs_cursor_y());
556                         error_box.create_objects(_("Error rendering data."));
557                         error_box.run_window();
558                 }
560 // Delete the progress box
561                 stop_progress();
567         } // !result
569 //      mwindow->gui->lock_window();
570 //      if(!result) mwindow->gui->statusbar->default_message();
571 //      mwindow->gui->unlock_window();
573 // Paste all packages into timeline if desired
575         if(!result && load_mode != LOAD_NOTHING)
576         {             // paste it in
577                 mwindow->gui->lock_window();
580                 mwindow->undo->update_undo_before(_("render"), LOAD_ALL);
583                 ArrayList<Asset*> *assets = packages->get_asset_list();
584                 if(load_mode == LOAD_PASTE)
585                         mwindow->clear(0);
586                 mwindow->load_assets(assets, 
587                         -1, 
588                         load_mode,
589                         0,
590                         0,
591                         mwindow->edl->session->labels_follow_edits,
592                         mwindow->edl->session->plugins_follow_edits);
593                 assets->remove_all_objects();
594                 delete assets;
597                 mwindow->save_backup();
598                 mwindow->undo->update_undo_after();
599                 mwindow->update_plugin_guis();
600                 mwindow->gui->update(1, 
601                         2,
602                         1,
603                         1,
604                         0,
605                         1,
606                         0);
607                 mwindow->sync_parameters(CHANGE_ALL);
608                 mwindow->gui->unlock_window();
609         }
611 // Need to restart because brender always stops before render.
612         mwindow->restart_brender();
613         if(farm_server) delete farm_server;
614         delete preferences;
615         delete command;
616         delete playback_config;
617         delete audio_cache;
618         delete video_cache;
619 // Must delete packages after server
620         delete packages;
621         delete default_asset;
622         in_progress = 0;
625 int Render::test_existence(MWindow *mwindow, Asset *asset)
627         int result = 0;
628         NewOrAppend window(mwindow);
629 // Append is not compatible with resample plugin.
630         result = window.test_file(asset);
631         switch(result)
632         {
633                 case 0:
634 //                      mwindow->purge_asset(asset->path);
635 //                      remove(asset->path);              // overwrite
636 //                      append_to_file = 0;
637                         break;
639                 case 1:
640                         result = 1;                      // cancel
641                         break;
643                 case 2:
644 //                                      append_to_file = 1;              // append
645                         result = 0;       // reset result;
646                         break;
647         }
648         return result;
652 void Render::create_filename(char *path, 
653         char *default_path, 
654         int current_number,
655         int total_digits,
656         int number_start)
658         int i, j, k;
659         int len = strlen(default_path);
660         char printf_string[BCTEXTLEN];
661         int found_number = 0;
663         for(i = 0, j = 0; i < number_start; i++, j++)
664         {
665                 printf_string[j] = default_path[i];
666         }
668 // Found the number
669         sprintf(&printf_string[j], "%%0%dd", total_digits);
670         j = strlen(printf_string);
671         i += total_digits;
673 // Copy remainder of string
674         for( ; i < len; i++, j++)
675         {
676                 printf_string[j] = default_path[i];
677         }
678         printf_string[j] = 0;
679 // Print the printf argument to the path
680         sprintf(path, printf_string, current_number);
683 void Render::get_starting_number(char *path, 
684         int &current_number,
685         int &number_start, 
686         int &total_digits,
687         int min_digits)
689         int i, j;
690         int len = strlen(path);
691         char number_text[BCTEXTLEN];
692         char *ptr = path;
694         total_digits = 0;
695         number_start = 0;
697 // Search for first 0.
698         ptr = strchr(ptr, '0');
700         if(ptr && isdigit(*ptr))
701         {
702                 number_start = ptr - path;
704 // Store the first number
705                 char *ptr2 = number_text;
706                 while(isdigit(*ptr))
707                         *ptr2++ = *ptr++;
708                 *ptr2++ = 0;
709                 current_number = atol(number_text);
710                 total_digits = strlen(number_text);
711         }
714 // No number found or number not long enough
715         if(total_digits < min_digits)
716         {
717                 current_number = 1;
718                 number_start = len;
719                 total_digits = min_digits;
720         }
729 int Render::load_defaults(Asset *asset)
731         mwindow->defaults->get("RENDER_PATH", asset->path);
732 //      to_tracks = mwindow->defaults->get("RENDER_TO_TRACKS", 1);
733         strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
734         load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
735         asset->audio_data = mwindow->defaults->get("RENDER_AUDIO", 1);
736         asset->video_data = mwindow->defaults->get("RENDER_VIDEO", 1);
737 //printf("Render::load_defaults 1 %d %d\n", asset->audio_data, asset->video_data);
739         char string[BCTEXTLEN];
740         sprintf(string, "WAV");
741         mwindow->defaults->get("RENDER_FORMAT", string);
742         sprintf(asset->vcodec, QUICKTIME_YUV2);
743         mwindow->defaults->get("RENDER_COMPRESSION", asset->vcodec);
745         asset->format = File::strtoformat(mwindow->plugindb, string);
747         asset->bits = mwindow->defaults->get("RENDER_BITS", 16);
748         asset->dither = mwindow->defaults->get("RENDER_DITHER", 0);
749         asset->signed_ = mwindow->defaults->get("RENDER_SIGNED", 1);
750         asset->byte_order = mwindow->defaults->get("RENDER_BYTE_ORDER", 1);
755         asset->load_defaults(mwindow->defaults);
756         mwindow->defaults->get("RENDER_AUDIO_CODEC", asset->acodec);
757         mwindow->defaults->get("RENDER_VIDEO_CODEC", asset->vcodec);
758 //printf("Render 1 %d\n", default_asset->divx_fix_bitrate);
760         return 0;
763 int Render::save_defaults(Asset *asset)
765 //printf("Render::save_defaults 1\n");
766         mwindow->defaults->update("RENDER_PATH", asset->path);
767 //      mwindow->defaults->update("RENDER_TO_TRACKS", to_tracks);
768         mwindow->defaults->update("RENDER_STRATEGY", strategy);
769         mwindow->defaults->update("RENDER_LOADMODE", load_mode);
770         mwindow->defaults->update("RENDER_AUDIO", asset->audio_data);
771         mwindow->defaults->update("RENDER_VIDEO", asset->video_data);
772 //printf("Render::save_defaults 2\n");
774         mwindow->defaults->update("RENDER_FORMAT", File::formattostr(mwindow->plugindb, asset->format));
775 //printf("Render::save_defaults 3\n");
777         mwindow->defaults->update("RENDER_VCODEC", asset->vcodec);
778         mwindow->defaults->update("RENDER_BITS", asset->bits);
779         mwindow->defaults->update("RENDER_DITHER", asset->dither);
780         mwindow->defaults->update("RENDER_SIGNED", asset->signed_);
781         mwindow->defaults->update("RENDER_BYTE_ORDER", asset->byte_order);
783         asset->save_defaults(mwindow->defaults);
784         mwindow->defaults->update("RENDER_AUDIO_CODEC", asset->acodec);
785         mwindow->defaults->update("RENDER_VIDEO_CODEC", asset->vcodec);
786 //printf("Render::save_defaults 4\n");
787         return 0;
793 #define WIDTH 410
794 #define HEIGHT 360
797 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
798  : BC_Window(PROGRAM_NAME ": Render", 
799         mwindow->gui->get_root_w() / 2 - WIDTH / 2,
800         mwindow->gui->get_root_h() / 2 - HEIGHT / 2,
801         WIDTH, 
802         HEIGHT,
803         (int)BC_INFINITY,
804         (int)BC_INFINITY,
805         0,
806         0,
807         1)
809         this->mwindow = mwindow;
810         this->render = render;
811         this->asset = asset;
814 RenderWindow::~RenderWindow()
816         delete format_tools;
817         delete loadmode;
822 int RenderWindow::create_objects()
824         int x = 5, y = 5;
825         add_subwindow(new BC_Title(x, 
826                 y, 
827                 (char*)((render->strategy == FILE_PER_LABEL || render->strategy == FILE_PER_LABEL_FARM) ? 
828                         _("Select the first file to render to:") : 
829                         _("Select a file to render to:"))));
830         y += 25;
832         format_tools = new FormatTools(mwindow,
833                                         this, 
834                                         asset);
835         format_tools->create_objects(x, 
836                 y, 
837                 1, 
838                 1, 
839                 1, 
840                 1, 
841                 0,
842                 1,
843                 0,
844                 0,
845                 &render->strategy,
846                 0);
848         loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
849         loadmode->create_objects();
851         add_subwindow(new BC_OKButton(this));
852         add_subwindow(new BC_CancelButton(this));
853         show_window();
854         return 0;