RafaMar + programmer friend Help button in Batch Render addition
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / packagerenderer.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 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 "arender.h"
23 #include "asset.h"
24 #include "auto.h"
25 #include "bctimer.h"
26 #include "brender.h"
27 #include "cache.h"
28 #include "clip.h"
29 #include "cwindow.h"
30 #include "cwindowgui.h"
31 #include "edit.h"
32 #include "edits.h"
33 #include "edl.h"
34 #include "edlsession.h"
35 #include "errorbox.h"
36 #include "file.h"
37 #include "filesystem.h"
38 #include "indexfile.h"
39 #include "language.h"
40 #include "mwindow.h"
41 #include "mwindowgui.h"
42 #include "packagerenderer.h"
43 #include "playabletracks.h"
44 #include "playbackconfig.h"
45 #include "pluginserver.h"
46 #include "preferences.h"
47 #include "render.h"
48 #include "renderengine.h"
49 #include "renderfarmfsserver.h"
50 #include "samples.h"
51 #include "sighandler.h"
52 #include "tracks.h"
53 #include "transportque.h"
54 #include "vedit.h"
55 #include "vframe.h"
56 #include "videodevice.h"
57 #include "vrender.h"
58
59
60
61
62
63
64
65 RenderPackage::RenderPackage()
66 {
67         audio_start = 0;
68         audio_end = 0;
69         video_start = 0;
70         video_end = 0;
71         audio_do = 0;
72         video_do = 0;
73         path[0] = 0;
74         done = 0;
75         use_brender = 0;
76 }
77
78 RenderPackage::~RenderPackage()
79 {
80 }
81
82
83 PackageFile::PackageFile(PackageRenderer *package_renderer)
84 {
85         this->package_renderer = package_renderer;
86 }
87
88 PackageFile::~PackageFile()
89 {
90 }
91
92 int PackageFile::write_frame_done(int64_t position)
93 {
94         if( !package_renderer->package->use_brender ) return 0;
95         return package_renderer->set_video_map(position, BRender::RENDERED);
96 }
97
98
99 // Used by RenderFarm and in the future, Render, to do packages.
100 PackageRenderer::PackageRenderer()
101 {
102         command = 0;
103         audio_cache = 0;
104         video_cache = 0;
105         aconfig = 0;
106         vconfig = 0;
107         timer = new Timer;
108         frames_per_second = 0;
109 }
110
111 PackageRenderer::~PackageRenderer()
112 {
113         delete command;
114         if( audio_cache )
115                 audio_cache->remove_user();
116         if( video_cache )
117                 video_cache->remove_user();
118         delete vconfig;
119         delete aconfig;
120         delete timer;
121 }
122
123 // PackageRenderer::initialize happens only once for every node when doing rendering session
124 // This is not called for each package!
125
126 int PackageRenderer::initialize(MWindow *mwindow,
127                 EDL *edl,
128                 Preferences *preferences,
129                 Asset *default_asset)
130 {
131         int result = 0;
132
133         this->mwindow = mwindow;
134         this->edl = edl;
135         this->preferences = preferences;
136         this->default_asset = default_asset;
137
138
139 //printf("PackageRenderer::initialize %d\n", preferences->processors);
140         command = new TransportCommand;
141         command->command = NORMAL_FWD;
142         command->get_edl()->copy_all(edl);
143         command->change_type = CHANGE_ALL;
144         command->set_playback_range();
145
146         default_asset->frame_rate = command->get_edl()->session->frame_rate;
147         default_asset->sample_rate = command->get_edl()->session->sample_rate;
148         default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
149                 command->get_edl()->session->aspect_h;
150         result = Render::check_asset(edl, *default_asset);
151
152         audio_cache = new CICache(preferences);
153         video_cache = new CICache(preferences);
154
155         //PlaybackConfig *config = command->get_edl()->session->playback_config;
156         aconfig = new AudioOutConfig();
157         vconfig = new VideoOutConfig;
158
159         return result;
160 }
161
162 void PackageRenderer::create_output()
163 {
164         FileSystem fs;
165         asset = new Asset(*default_asset);
166
167         if( !get_master() && preferences->renderfarm_vfs && preferences->use_renderfarm )
168                 snprintf(asset->path, sizeof(asset->path),
169                         RENDERFARM_FS_PREFIX "%s", package->path);
170         else
171                 strncpy(asset->path, package->path, sizeof(asset->path));
172
173         file = new PackageFile(this);
174         file->set_processors(preferences->processors);
175         result = file->open_file(preferences, asset, 0, 1);
176
177         if( result && mwindow ) {
178 // open failed
179                 char string[BCTEXTLEN];
180                 snprintf(string, sizeof(string), _("Couldn't open %s"), asset->path);
181                 ErrorBox error(_(PROGRAM_NAME ": Error"),
182                         mwindow->gui->get_abs_cursor_x(1),
183                         mwindow->gui->get_abs_cursor_y(1));
184                 error.create_objects(string);
185                 error.run_window();
186         }
187         else
188         if( mwindow ) {
189                 mwindow->sighandler->push_file(file);
190                 IndexFile::delete_index(preferences, asset);
191         }
192 //printf("PackageRenderer::create_output %d %d\n", __LINE__, result);
193 }
194
195 void PackageRenderer::create_engine()
196 {
197 // Fix audio buffers to 1 second
198         audio_read_length = command->get_edl()->session->sample_rate;
199         command->get_edl()->session->playback_config->aconfig->fragment_size = audio_read_length;
200
201         aconfig->fragment_size = audio_read_length;
202
203
204         render_engine = new RenderEngine(0, preferences, 0, 0);
205         render_engine->set_acache(audio_cache);
206         render_engine->set_vcache(video_cache);
207         render_engine->arm_command(command);
208
209         if( package->use_brender ) {
210                 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
211                         default_asset->frame_rate *
212                         default_asset->sample_rate);
213                 video_preroll = preferences->brender_preroll;
214         }
215         else {
216                 audio_preroll = Units::to_int64(preferences->render_preroll *
217                         default_asset->sample_rate);
218                 video_preroll = Units::to_int64(preferences->render_preroll *
219                         default_asset->frame_rate);
220         }
221         audio_position = package->audio_start - audio_preroll;
222         if( audio_position < 0 ) {
223                 audio_preroll += audio_position;
224                 audio_position = 0;
225         }
226         video_position = package->video_start - video_preroll;
227         if( video_position < 0 ) {
228                 video_preroll += video_position;
229                 video_position = 0;
230         }
231
232
233 //      PRINT_TRACE
234
235 // Create output buffers
236         if( asset->audio_data ) {
237                 file->start_audio_thread(audio_read_length,
238                         preferences->processors > 1 ? 2 : 1);
239         }
240
241 //      PRINT_TRACE
242
243         if( asset->video_data ) {
244                 compressed_output = new VFrame;
245 // The write length needs to correlate with the processor count because
246 // it is passed to the file handler which usually processes frames simultaneously.
247                 video_write_length = preferences->processors;
248                 video_write_position = 0;
249                 direct_frame_copying = 0;
250
251
252 //printf("PackageRenderer::create_engine %d video_write_length=%d\n", __LINE__, video_write_length);
253 // starting frames are corrupted if video_write_length > 2.  Work around it, for now.
254                 if( video_write_length > 2 ) {
255                         video_write_length = 2;
256                 }
257                 file->start_video_thread(video_write_length,
258                         command->get_edl()->session->color_model,
259                         preferences->processors > 1 ? 2 : 1,
260                         0);
261 //printf("PackageRenderer::create_engine %d\n", __LINE__);
262
263
264                 if( mwindow ) {
265                         video_device = new VideoDevice;
266                         video_device->open_output(vconfig,
267                                 command->get_edl()->session->frame_rate,
268                                 command->get_edl()->session->output_w,
269                                 command->get_edl()->session->output_h,
270                                 mwindow->cwindow->gui->canvas,
271                                 0);
272 //                      video_device->start_playback();
273                 }
274         }
275
276
277         playable_tracks = new PlayableTracks(render_engine->get_edl(),
278                 video_position,
279                 PLAY_FORWARD,
280                 TRACK_VIDEO,
281                 1);
282
283 }
284
285
286
287
288 void PackageRenderer::do_audio()
289 {
290 //printf("PackageRenderer::do_audio %d\n", __LINE__);
291 // Do audio data
292         if( asset->audio_data ) {
293                 audio_output = file->get_audio_buffer();
294 // Zero unused channels in output vector
295                 for( int i = 0; i < MAX_CHANNELS; i++ ) {
296                         audio_output_ptr[i] = (i < asset->channels) ?
297                                 audio_output[i] :
298                                 0;
299                 }
300
301
302
303 // Call render engine
304
305                 result = render_engine->arender->process_buffer(audio_output_ptr,
306                         audio_read_length,
307                         audio_position);
308
309
310
311 // Fix buffers for preroll
312                 int64_t output_length = audio_read_length;
313                 if( audio_preroll > 0 ) {
314                         if( audio_preroll >= output_length )
315                                 output_length = 0;
316                         else {
317                                 output_length -= audio_preroll;
318                                 for( int i = 0; i < MAX_CHANNELS; i++ ) {
319                                         if( audio_output_ptr[i] ) {
320                                                 double *data = audio_output_ptr[i]->get_data();
321                                                 for( int j = 0; j < output_length; j++ ) {
322                                                         data[j] = data[j + audio_read_length - output_length];
323                                                 }
324                                         }
325                                 }
326                         }
327 //printf("PackageRenderer::do_audio 4\n");
328
329                         audio_preroll -= audio_read_length;
330                 }
331
332 // Must perform writes even if 0 length so get_audio_buffer doesn't block
333                 result |= file->write_audio_buffer(output_length);
334         }
335
336         audio_position += audio_read_length;
337 //printf("PackageRenderer::do_audio %d\n", __LINE__);
338 }
339
340
341 void PackageRenderer::do_video()
342 {
343 // Do video data
344         if( asset->video_data ) {
345 // get the absolute video position from the audio position
346                 int64_t video_end = video_position + video_read_length;
347
348                 if( video_end > package->video_end )
349                         video_end = package->video_end;
350
351                 while( !result && video_position < video_end ) {
352 // Try to copy the compressed frame directly from the input to output files
353                         if( direct_frame_copy(command->get_edl(),
354                                         video_position, file, result) ) {
355 // Direct frame copy failed.
356 // Switch back to background compression
357                                 if( direct_frame_copying ) {
358
359                                         file->start_video_thread(video_write_length,
360                                                 command->get_edl()->session->color_model,
361                                                 preferences->processors > 1 ? 2 : 1,
362                                                 0);
363 //printf("PackageRenderer::do_video %d %d\n", __LINE__, preferences->processors);
364                                         direct_frame_copying = 0;
365                                 }
366
367 // Try to use the rendering engine to write the frame.
368 // Get a buffer for background writing.
369
370                                 if( video_write_position == 0 )
371                                         video_output = file->get_video_buffer();
372 // Construct layered output buffer
373                                 video_output_ptr = video_output[0][video_write_position];
374
375                                 if( !result )
376                                         result = render_engine->vrender->process_buffer(
377                                                 video_output_ptr, video_position, 0);
378                                 if( !result &&
379                                         mwindow &&
380                                         video_device->output_visible() ) {
381 // Vector for video device
382                                         VFrame *preview_output;
383
384                                         video_device->new_output_buffer(&preview_output,
385                                                 command->get_edl()->session->color_model,
386                                                 command->get_edl());
387
388                                         preview_output->copy_from(video_output_ptr);
389                                         video_device->write_buffer(preview_output,
390                                                 command->get_edl());
391                                 }
392 // Don't write to file
393                                 if( video_preroll && !result ) {
394                                         video_preroll--;
395 // Keep the write position at 0 until ready to write real frames
396                                         result = file->write_video_buffer(0);
397                                         video_write_position = 0;
398                                 }
399                                 else
400                                 if( !result ) {
401 // Set background rendering parameters
402 // Allow us to skip sections of the output file by setting the frame number.
403 // Used by background render and render farm.
404                                         video_output_ptr->set_number(video_position);
405                                         video_write_position++;
406
407                                         if( video_write_position >= video_write_length ) {
408                                                 result = file->write_video_buffer(video_write_position);
409                                                 video_write_position = 0;
410                                         }
411                                 }
412                         }
413
414                         video_position++;
415                         if( !result && get_result() ) result = 1;
416                         if( !result && progress_cancelled() ) result = 1;
417                 }
418         }
419         else {
420                 video_position += video_read_length;
421         }
422 }
423
424
425 void PackageRenderer::stop_engine()
426 {
427         delete render_engine;
428         delete playable_tracks;
429 }
430
431
432 void PackageRenderer::stop_output()
433 {
434         int error = 0;
435         if( asset->audio_data ) {
436 // stop file I/O
437                 file->stop_audio_thread();
438         }
439
440         if( asset->video_data ) {
441                 delete compressed_output;
442                 if( video_write_position )
443                         file->write_video_buffer(video_write_position);
444                 video_write_position = 0;
445                 if( !error ) file->stop_video_thread();
446                 if( mwindow ) {
447 //                      video_device->stop_playback();
448                         video_device->close_all();
449                         delete video_device;
450                 }
451         }
452 }
453
454
455 void PackageRenderer::close_output()
456 {
457         if( mwindow )
458                 mwindow->sighandler->pull_file(file);
459         file->close_file();
460         delete file;
461         asset->Garbage::remove_user();
462 }
463
464 // Aborts and returns 1 if an error is encountered.
465 int PackageRenderer::render_package(RenderPackage *package)
466 {
467         int audio_done = 0;
468         int video_done = 0;
469         int samples_rendered = 0;
470         const int debug = 0;
471
472
473         result = 0;
474         this->package = package;
475
476 // printf(
477 // "PackageRenderer::render_package: audio s=%jd l=%jd video s=%jd l=%jd\n",
478 //      package->audio_start,
479 //      package->audio_end - package->audio_start,
480 //      package->video_start,
481 //      package->video_end - package->video_start);
482
483         if( debug ) PRINT_TRACE
484
485         if( package->video_do ) default_asset->video_data = 1;
486         if( package->audio_do ) default_asset->audio_data = 1;
487         Render::check_asset(edl, *default_asset);
488
489 // FIXME: The design that we only get EDL once does not give us neccessary flexiblity to do things the way they should be donek
490         default_asset->video_data = package->video_do;
491         default_asset->audio_data = package->audio_do;
492         Render::check_asset(edl, *default_asset);
493
494         create_output();
495
496         if( !asset->video_data ) video_done = 1;
497         if( !asset->audio_data ) audio_done = 1;
498
499 // Create render engine
500         if( !result ) {
501                 create_engine();
502 // Main loop
503                 timer->update();
504                 total_samples_rendered = 0;
505                 while( !result && (!audio_done || !video_done) ) {
506                         int need_audio = 0, need_video = 0;
507 // Calculate lengths to process.  Audio fragment is constant.
508                         if( !audio_done ) {
509                                 if( audio_position + audio_read_length >= package->audio_end ) {
510                                         audio_done = 1;
511                                         audio_read_length = package->audio_end - audio_position;
512                                 }
513
514                                 samples_rendered = audio_read_length;
515                                 need_audio = 1;
516                         }
517
518 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
519
520                         if( !video_done ) {
521                                 if( audio_done ) {
522 //                                      video_read_length = package->video_end - video_position;
523 // // Packetize video length so progress gets updated
524 //                                      video_read_length = (int)MIN(asset->frame_rate, video_read_length);
525 //                                      video_read_length = MAX(video_read_length, 30);
526                                         video_read_length = 1;
527                                 }
528                                 else {
529 // Guide video with audio
530                                         video_read_length = Units::to_int64(
531                                                 (double)(audio_position + audio_read_length) /
532                                                 asset->sample_rate *
533                                                 asset->frame_rate) -
534                                                 video_position;
535                                 }
536
537 // Clamp length
538                                 if( video_position + video_read_length >= package->video_end ) {
539                                         video_done = 1;
540                                         video_read_length = package->video_end - video_position;
541                                 }
542
543 // Calculate samples rendered for progress bar.
544                                 if( audio_done )
545                                         samples_rendered = Units::round((double)video_read_length /
546                                                 asset->frame_rate *
547                                                 asset->sample_rate);
548
549                                 need_video = 1;
550                         }
551                         if( need_video && !result ) do_video();
552                         if( need_audio && !result ) do_audio();
553
554                         if( debug ) PRINT_TRACE
555                         if( !result ) {
556 // Calculate frames per second for the renderfarm table.
557                                 total_samples_rendered += samples_rendered;
558                                 if( !video_done && timer->get_difference() > 30000 ) {
559                                         frames_per_second = (double)total_samples_rendered *
560                                                 asset->frame_rate /
561                                                 asset->sample_rate /
562                                                 ((double)timer->get_difference() / 1000);
563                                 }
564                                 set_progress(samples_rendered);
565                         }
566
567                         if( !result && progress_cancelled() ) result = 1;
568
569 // audio_read_length, video_read_length, samples_rendered, result);
570                         if( result )
571                                 set_result(result);
572                         else
573                                 result = get_result();
574                 }
575
576 // Final FPS readout
577                 frames_per_second = (double)(package->video_end - package->video_start) /
578                         ((double)timer->get_difference() / 1000);
579
580
581 //PRINT_TRACE
582                 stop_engine();
583 //PRINT_TRACE
584
585                 stop_output();
586 //PRINT_TRACE
587
588
589         }
590
591
592 //PRINT_TRACE
593
594         close_output();
595
596 //PRINT_TRACE
597
598         set_result(result);
599 //PRINT_TRACE
600
601
602
603         return result;
604 }
605
606
607
608
609
610
611
612
613 // Try to copy the compressed frame directly from the input to output files
614 // Return 1 on failure and 0 on success
615 int PackageRenderer::direct_frame_copy(EDL *edl,
616         int64_t &video_position,
617         File *file,
618         int &error)
619 {
620         Track *playable_track = 0;
621         Edit *playable_edit = 0;
622
623 //printf("Render::direct_frame_copy 1\n");
624         if( direct_copy_possible(edl,
625                 video_position,
626                 playable_track,
627                 playable_edit,
628                 file) ) {
629 // Switch to direct copying
630                 if( !direct_frame_copying ) {
631                         if( video_write_position ) {
632                                 error |= file->write_video_buffer(video_write_position);
633                                 video_write_position = 0;
634                         }
635                         file->stop_video_thread();
636                         direct_frame_copying = 1;
637                 }
638 //printf("Render::direct_frame_copy 2\n");
639
640                 if( !package->use_brender ) {
641                         error |= ((VEdit*)playable_edit)->read_frame(compressed_output,
642                                 video_position,
643                                 PLAY_FORWARD,
644                                 video_cache,
645                                 1,
646                                 0,
647                                 0);
648 //printf("Render::direct_frame_copy %d %d\n", __LINE__, compressed_output->get_compressed_size());
649                 }
650                 
651
652                 if( !error && video_preroll > 0 ) {
653                         video_preroll--;
654                 }
655                 else
656                 if( !error ) {
657                         if( package->use_brender ) {
658 //printf("PackageRenderer::direct_frame_copy 1\n");
659                                 error = set_video_map(video_position, BRender::SCANNED);
660 //printf("PackageRenderer::direct_frame_copy 10 %d\n", error);
661                         }
662                         else {
663                                 VFrame ***temp_output = new VFrame**[1];
664                                 temp_output[0] = new VFrame*[1];
665                                 temp_output[0][0] = compressed_output;
666                                 error = file->write_frames(temp_output, 1);
667                                 delete [] temp_output[0];
668                                 delete [] temp_output;
669                         }
670                 }
671                 return 0;
672         }
673         else
674                 return 1;
675 }
676
677 int PackageRenderer::direct_copy_possible(EDL *edl,
678                                 int64_t current_position,
679                                 Track* &playable_track,  // The one track which is playable
680                                 Edit* &playable_edit, // The edit which is playing
681                                 File *file)   // Output file
682 {
683         int result = 1;
684         int total_playable_tracks = 0;
685         Track* current_track;
686
687 // Number of playable tracks must equal 1
688         for( current_track = edl->tracks->first;
689                 current_track && result;
690                 current_track = current_track->next ) {
691                 if( current_track->data_type == TRACK_VIDEO ) {
692                         if( playable_tracks->is_playable(current_track,
693                                 current_position,
694                                 PLAY_FORWARD,
695                                 1) ) {
696                                 playable_track = current_track;
697                                 total_playable_tracks++;
698                         }
699                 }
700         }
701
702 //printf("Render::direct_copy_possible 1 %d\n", result);
703         if( total_playable_tracks != 1 ) result = 0;
704 //printf("Render::direct_copy_possible 2 %d\n", result);
705
706 // Edit must have a source file
707 // TODO: descend into nested EDL's
708         if( result ) {
709 //printf("Render::direct_copy_possible 3 %d\n", result);
710                 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
711 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
712                 if( !playable_edit )
713                         result = 0;
714         }
715
716 // Source file must be able to copy to destination file.
717 // Source file must be same size as project output.
718         if( result ) {
719                 if( !file->can_copy_from(playable_edit->asset,
720                         current_position + playable_track->nudge,
721                         edl->session->output_w,
722                         edl->session->output_h) )
723                         result = 0;
724         }
725 //printf("Render::direct_copy_possible 6 %d\n", result);
726
727 // Test conditions mutual between vrender.C and this.
728         if( result &&
729                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1) )
730                 result = 0;
731 //printf("Render::direct_copy_possible 7 %d\n", result);
732
733         return result;
734 }
735
736
737
738
739
740
741
742
743
744 int PackageRenderer::get_master()
745 {
746         return 0;
747 }
748
749 // Get result status from server
750 int PackageRenderer::get_result()
751 {
752         return 0;
753 }
754
755 void PackageRenderer::set_result(int value)
756 {
757 }
758
759 void PackageRenderer::set_progress(int64_t value)
760 {
761 }
762
763 int PackageRenderer::set_video_map(int64_t position, int value)
764 {
765         return 0;
766 }
767
768 int PackageRenderer::progress_cancelled()
769 {
770         return 0;
771 }
772
773
774
775
776
777
778
779
780
781