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