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