Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / packagerenderer.C
blob05127798d6775ebdb8f7c9d43362d314494372a3
1 #include "arender.h"
2 #include "asset.h"
3 #include "auto.h"
4 #include "brender.h"
5 #include "cache.h"
6 #include "clip.h"
7 #include "cwindow.h"
8 #include "cwindowgui.h"
9 #include "edit.h"
10 #include "edits.h"
11 #include "edl.h"
12 #include "edlsession.h"
13 #include "errorbox.h"
14 #include "file.h"
15 #include "filesystem.h"
16 #include "indexfile.h"
17 #include "language.h"
18 #include "mwindow.h"
19 #include "mwindowgui.h"
20 #include "packagerenderer.h"
21 #include "playabletracks.h"
22 #include "playbackconfig.h"
23 #include "pluginserver.h"
24 #include "preferences.h"
25 #include "render.h"
26 #include "renderengine.h"
27 #include "renderfarmfsserver.h"
28 #include "sighandler.h"
29 #include "tracks.h"
30 #include "transportque.h"
31 #include "vedit.h"
32 #include "vframe.h"
33 #include "videodevice.h"
34 #include "vrender.h"
42 RenderPackage::RenderPackage()
44         audio_start = 0;
45         audio_end = 0;
46         video_start = 0;
47         video_end = 0;
48         path[0] = 0;
49         done = 0;
50         use_brender = 0;
53 RenderPackage::~RenderPackage()
64 // Used by RenderFarm and in the future, Render, to do packages.
65 PackageRenderer::PackageRenderer()
67         command = 0;
68         audio_cache = 0;
69         video_cache = 0;
70         aconfig = 0;
71         vconfig = 0;
74 PackageRenderer::~PackageRenderer()
76         delete command;
77         delete audio_cache;
78         delete video_cache;
79         delete vconfig;
80         delete aconfig;
83 // PackageRenderer::initialize happens only once for every node when doing rendering session
84 // This is not called for each package!
86 int PackageRenderer::initialize(MWindow *mwindow,
87                 EDL *edl, 
88                 Preferences *preferences, 
89                 Asset_GC default_asset,
90                 ArrayList<PluginServer*> *plugindb)
92         int result = 0;
94         this->mwindow = mwindow;
95         this->edl = edl;
96         this->preferences = preferences;
97         this->default_asset = default_asset;
98         this->plugindb = plugindb;
101 //printf("PackageRenderer::initialize %d\n", preferences->processors);
102         command = new TransportCommand;
103         command->command = NORMAL_FWD;
104         command->get_edl()->copy_all(edl);
105         command->change_type = CHANGE_ALL;
106         command->set_playback_range(edl);
108         default_asset->frame_rate = command->get_edl()->session->frame_rate;
109         default_asset->sample_rate = command->get_edl()->session->sample_rate;
110         default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
111                 command->get_edl()->session->aspect_h;
112         result = Render::check_asset(edl, *default_asset);
114         audio_cache = new CICache(preferences, plugindb);
115         video_cache = new CICache(preferences, plugindb);
117         PlaybackConfig *config = command->get_edl()->session->playback_config;
118         aconfig = new AudioOutConfig(0);
119         vconfig = new VideoOutConfig;
121         return result;
124 void PackageRenderer::create_output()
126         FileSystem fs;
127         asset = Asset_GC(new Asset(*default_asset));
133         strcpy(asset->path, package->path);
136         
138         file = new File;
140         file->set_processors(preferences->processors);
142         result = file->open_file(preferences, 
143                                         asset, 
144                                         0, 
145                                         1, 
146                                         command->get_edl()->session->sample_rate, 
147                                         command->get_edl()->session->frame_rate);
148 //printf("PackageRenderer::create_output 10 %d\n", result);
150         if(result && mwindow)
151         {
152 // open failed
153                 char string[BCTEXTLEN];
154                 sprintf(string, _("Couldn't open %s"), asset->path);
155                 ErrorBox error(PROGRAM_NAME ": Error",
156                         mwindow->gui->get_abs_cursor_x(1),
157                         mwindow->gui->get_abs_cursor_y(1));
158                 error.create_objects(string);
159                 error.run_window();
160         }
161         else
162         if(mwindow)
163         {
164                 mwindow->sighandler->push_file(file);
165                 IndexFile::delete_index(preferences, asset);
166         }
167 //printf("PackageRenderer::create_output 100 %d\n", result);
170 void PackageRenderer::create_engine()
172         int current_achannel = 0, current_vchannel = 0;
173         audio_read_length = command->get_edl()->session->sample_rate;
175         aconfig->fragment_size = audio_read_length;
178         render_engine = new RenderEngine(0,
179                 preferences,
180                 command,
181                 0,
182                 plugindb,
183                 0);
184         render_engine->set_acache(audio_cache);
185         render_engine->set_vcache(video_cache);
186         render_engine->arm_command(command, current_achannel, current_vchannel);
188         if(package->use_brender)
189         {
190                 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
191                         default_asset->frame_rate *
192                         default_asset->sample_rate);
193                 video_preroll = preferences->brender_preroll;
194         }
195         else
196         {
197                 audio_preroll = Units::to_int64(preferences->render_preroll * 
198                         default_asset->sample_rate);
199                 video_preroll = Units::to_int64(preferences->render_preroll * 
200                         default_asset->frame_rate);
201         }
202         audio_position = package->audio_start - audio_preroll;
203         video_position = package->video_start - video_preroll;
208 // Create output buffers
209         if(asset->audio_data)
210         {
211                 file->start_audio_thread(audio_read_length, 
212                         preferences->processors > 1 ? 2 : 1);
213         }
216         if(asset->video_data)
217         {
218                 compressed_output = new VFrame;
219 // The write length needs to correlate with the processor count because
220 // it is passed to the file handler which usually processes frames simultaneously.
221                 video_write_length = preferences->processors;
222                 video_write_position = 0;
223                 direct_frame_copying = 0;
226 //printf("PackageRenderer::create_engine 1\n");
227                 file->start_video_thread(video_write_length,
228                         command->get_edl()->session->color_model,
229                         preferences->processors > 1 ? 2 : 1,
230                         0);
233                 if(mwindow)
234                 {
235                         video_device = new VideoDevice;
236                         video_device->open_output(vconfig, 
237                                 command->get_edl()->session->frame_rate, 
238                                 command->get_edl()->session->output_w, 
239                                 command->get_edl()->session->output_h, 
240                                 mwindow->cwindow->gui->canvas,
241                                 0);
242                         video_device->start_playback();
243                 }
244         }
247         playable_tracks = new PlayableTracks(render_engine, 
248                 video_position, 
249                 TRACK_VIDEO,
250                 1);
257 void PackageRenderer::do_audio()
259 //printf("PackageRenderer::do_audio 1\n");
260 // Do audio data
261         if(asset->audio_data)
262         {
263                 audio_output = file->get_audio_buffer();
264 // Zero unused channels in output vector
265                 for(int i = 0; i < MAX_CHANNELS; i++)
266                         audio_output_ptr[i] = (i < asset->channels) ? 
267                                 audio_output[i] : 
268                                 0;
273 // Call render engine
274                 result = render_engine->arender->process_buffer(audio_output_ptr, 
275                         audio_read_length, 
276                         audio_position,
277                         0);
279 //printf("PackageRenderer::do_audio 3\n");
282 // Fix buffers for preroll
283                 int64_t output_length = audio_read_length;
284                 if(audio_preroll > 0)
285                 {
286                         if(audio_preroll >= output_length)
287                                 output_length = 0;
288                         else
289                         {
290                                 output_length -= audio_preroll;
291                                 for(int i = 0; i < MAX_CHANNELS; i++)
292                                 {
293                                         if(audio_output_ptr[i])
294                                                 for(int j = 0; j < output_length; j++)
295                                                 {
296                                                         audio_output_ptr[i][j] = audio_output_ptr[i][j + audio_read_length - output_length];
297                                                 }
298                                 }
299                         }
300 //printf("PackageRenderer::do_audio 4\n");
302                         audio_preroll -= audio_read_length;
303                 }
305 // Must perform writes even if 0 length so get_audio_buffer doesn't block
306                 result |= file->write_audio_buffer(output_length);
307         }
309         audio_position += audio_read_length;
310 //printf("PackageRenderer::do_audio 5\n");
314 void PackageRenderer::do_video()
316 // Do video data
317         if(asset->video_data)
318         {
319 // get the absolute video position from the audio position
320                 int64_t video_end = video_position + video_read_length;
322                 if(video_end > package->video_end)
323                         video_end = package->video_end;
325                 while(video_position < video_end && !result)
326                 {
327 // Try to copy the compressed frame directly from the input to output files
328 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
329                         if(direct_frame_copy(command->get_edl(), 
330                                 video_position, 
331                                 file, 
332                                 result))
333                         {
334 // Direct frame copy failed.
335 // Switch back to background compression
336                                 if(direct_frame_copying)
337                                 {
338                                         file->start_video_thread(video_write_length, 
339                                                 command->get_edl()->session->color_model,
340                                                 preferences->processors > 1 ? 2 : 1,
341                                                 0);
342                                         direct_frame_copying = 0;
343                                 }
345 // Try to use the rendering engine to write the frame.
346 // Get a buffer for background writing.
350                                 if(video_write_position == 0)
351                                         video_output = file->get_video_buffer();
357 // Construct layered output buffer
358                                 video_output_ptr = video_output[0][video_write_position];
360                                 if(!result)
361                                         result = render_engine->vrender->process_buffer(
362                                                 video_output_ptr, 
363                                                 video_position, 
364                                                 0);
368                                 if(!result && 
369                                         mwindow && 
370                                         video_device->output_visible())
371                                 {
372 // Vector for video device
373                                         VFrame *preview_output;
375                                         video_device->new_output_buffer(&preview_output,
376                                                 command->get_edl()->session->color_model);
378                                         preview_output->copy_from(video_output_ptr);
379                                         video_device->write_buffer(preview_output, 
380                                                 command->get_edl());
381                                 }
385 // Don't write to file
386                                 if(video_preroll && !result)
387                                 {
388                                         video_preroll--;
389 // Keep the write position at 0 until ready to write real frames
390                                         result = file->write_video_buffer(0);
391                                         video_write_position = 0;
392                                 }
393                                 else
394                                 if(!result)
395                                 {
396 // Set background rendering parameters
397 // Allow us to skip sections of the output file by setting the frame number.
398 // Used by background render and render farm.
399                                         video_output_ptr->set_number(video_position);
400                                         video_write_position++;
402                                         if(video_write_position >= video_write_length)
403                                         {
404 //printf("PackageRenderer::do_video 9\n");
405                                                 result = file->write_video_buffer(video_write_position);
406 // Update the brender map after writing the files.
407                                                 if(package->use_brender)
408                                                 {
409 //printf("PackageRenderer::do_video 10\n");
410                                                         for(int i = 0; i < video_write_position && !result; i++)
411                                                         {
412                                                                 result = set_video_map(video_position + 1 - video_write_position + i, 
413                                                                         BRender::RENDERED);
414                                                         }
415 //printf("PackageRenderer::do_video 11 %d\n", result);
416                                                 }
417                                                 video_write_position = 0;
418                                         }
419                                 }
422                         }
424                         video_position++;
425                         if(!result && get_result()) result = 1;
426                         if(!result && progress_cancelled()) result = 1;
427                 }
428         }
429         else
430         {
431                 video_position += video_read_length;
432         }
436 void PackageRenderer::stop_engine()
438         delete render_engine;
439         delete playable_tracks;
443 void PackageRenderer::stop_output()
445         int error = 0;
446         if(asset->audio_data)
447         {
448 // stop file I/O
449                 file->stop_audio_thread();
450         }
452         if(asset->video_data)
453         {
454                 delete compressed_output;
455                 if(video_write_position)
456                         file->write_video_buffer(video_write_position);
457                 if(package->use_brender)
458                 {
459                         for(int i = 0; i < video_write_position && !error; i++)
460                         {
461                                 error = set_video_map(video_position - video_write_position + i, 
462                                         BRender::RENDERED);
463                         }
464                 }
465                 video_write_position = 0;       
466                 if(!error) file->stop_video_thread();
467                 if(mwindow)
468                 {
469                         video_device->stop_playback();
470                         video_device->close_all();
471                         delete video_device;
472                 }
473         }
477 void PackageRenderer::close_output()
479         if(mwindow)
480                 mwindow->sighandler->pull_file(file);
481         file->close_file();
482         delete file;
485 // Aborts and returns 1 if an error is encountered.
486 int PackageRenderer::render_package(RenderPackage *package)
488         int audio_done = 0;
489         int video_done = 0;
490         int samples_rendered = 0;
493         result = 0;
494         this->package = package;
496 // printf(
497 // "PackageRenderer::render_package: audio s=%lld l=%lld video s=%lld l=%lld\n",
498 //      package->audio_start, 
499 //      package->audio_end - package->audio_start, 
500 //      package->video_start, 
501 //      package->video_end - package->video_start);
504 // FIXME: The design that we only get EDL once does not give us neccessary flexiblity to do things the way they should be donek
505         default_asset->video_data = package->video_do;
506         default_asset->audio_data = package->audio_do;
507         Render::check_asset(edl, *default_asset);
508         
509         create_output();
511         if(!asset->video_data) video_done = 1;
512         if(!asset->audio_data) audio_done = 1;
514 // Create render engine
515         if(!result)
516         {
517                 create_engine();
519 //printf("PackageRenderer::render_package 5 %d\n", result);
521 // Main loop
522                 while((!audio_done || !video_done) && !result)
523                 {
524                         int need_audio = 0, need_video = 0;
529 // Calculate lengths to process.  Audio fragment is constant.
530                         if(!audio_done)
531                         {
532                                 if(audio_position + audio_read_length >= package->audio_end)
533                                 {
534                                         audio_done = 1;
535                                         audio_read_length = package->audio_end - audio_position;
536                                 }
538                                 samples_rendered = audio_read_length;
539                                 need_audio = 1;
540                         }
542 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
544                         if(!video_done)
545                         {
546                                 if(audio_done)
547                                 {
548                                         video_read_length = package->video_end - video_position;
549 // Packetize video length so progress gets updated
550                                         video_read_length = (int)MIN(asset->frame_rate, video_read_length);
551                                         video_read_length = MAX(video_read_length, 30);
552                                 }
553                                 else
554 // Guide video with audio
555                                 {
556                                         video_read_length = Units::to_int64(
557                                                 (double)(audio_position + audio_read_length) / 
558                                                 asset->sample_rate * 
559                                                 asset->frame_rate) - 
560                                                 video_position;
561                                 }
563 // Clamp length
564                                 if(video_position + video_read_length >= package->video_end)
565                                 {
566                                         video_done = 1;
567                                         video_read_length = package->video_end - video_position;
568                                 }
570 // Calculate samples rendered for progress bar.
571                                 if(audio_done)
572                                         samples_rendered = Units::round((double)video_read_length /
573                                                 asset->frame_rate *
574                                                 asset->sample_rate);
576                                 need_video = 1;
577                         }
579 //printf("PackageRenderer::render_package 1 %d %lld %lld\n", result, audio_read_length, video_read_length);
580                         if(need_video && !result) do_video();
581 //printf("PackageRenderer::render_package 7 %d %d\n", result, samples_rendered);
582                         if(need_audio && !result) do_audio();
585                         if(!result) set_progress(samples_rendered);
591                         if(!result && progress_cancelled()) result = 1;
593 // printf("PackageRenderer::render_package 10 %d %d %d %d\n", 
594 // audio_read_length, video_read_length, samples_rendered, result);
595                         if(result) 
596                                 set_result(result);
597                         else
598                                 result = get_result();
599                 }
601 //printf("PackageRenderer::render_package 20\n");
602                 stop_engine();
603 //printf("PackageRenderer::render_package 30\n");
605                 stop_output();
606 //printf("PackageRenderer::render_package 40\n");
609         }
613 //printf("PackageRenderer::render_package 50\n");
614         close_output();
615 //printf("PackageRenderer::render_package 60\n");
618         set_result(result);
619 //printf("PackageRenderer::render_package 70\n");
623         return result;
633 // Try to copy the compressed frame directly from the input to output files
634 // Return 1 on failure and 0 on success
635 int PackageRenderer::direct_frame_copy(EDL *edl, 
636         int64_t &video_position, 
637         File *file,
638         int &error)
640         Track *playable_track;
641         Edit *playable_edit;
642         int64_t frame_size;
644 //printf("Render::direct_frame_copy 1\n");
645         if(direct_copy_possible(edl, 
646                 video_position, 
647                 playable_track, 
648                 playable_edit, 
649                 file))
650         {
651 // Switch to direct copying
652                 if(!direct_frame_copying)
653                 {
654                         if(video_write_position)
655                         {
656                                 error |= file->write_video_buffer(video_write_position);
657                                 video_write_position = 0;
658                         }
659                         file->stop_video_thread();
660                         direct_frame_copying = 1;
661                 }
662 //printf("Render::direct_frame_copy 2\n");
664                 if(!package->use_brender)
665                         error |= ((VEdit*)playable_edit)->read_frame(compressed_output, 
666                                 video_position,
667                                 PLAY_FORWARD,
668                                 video_cache,
669                                 1,
670                                 0,
671                                 0);
674                 if(!error && video_preroll > 0)
675                 {
676                         video_preroll--;
677                 }
678                 else
679                 if(!error)
680                 {
681                         if(package->use_brender)
682                         {
683 //printf("PackageRenderer::direct_frame_copy 1\n");
684                                 error = set_video_map(video_position, BRender::SCANNED);
685 //printf("PackageRenderer::direct_frame_copy 10 %d\n", error);
686                         }
687                         else
688                         {
689                                 VFrame ***temp_output = new VFrame**[1];
690                                 temp_output[0] = new VFrame*[1];
691                                 temp_output[0][0] = compressed_output;
692                                 error = file->write_frames(temp_output, 1);
693                                 delete [] temp_output[0];
694                                 delete temp_output;
695                         }
696                 }
697                 return 0;
698         }
699         else
700                 return 1;
703 int PackageRenderer::direct_copy_possible(EDL *edl,
704                                 int64_t current_position, 
705                                 Track* playable_track,  // The one track which is playable
706                                 Edit* &playable_edit, // The edit which is playing
707                                 File *file)   // Output file
709         int result = 1;
710         int total_playable_tracks = 0;
711         Track* current_track;
712         Patch* current_patch;
713         Auto* current_auto;
714         int temp;
716 // Number of playable tracks must equal 1
717         for(current_track = edl->tracks->first;
718                 current_track && result; 
719                 current_track = current_track->next)
720         {
721                 if(current_track->data_type == TRACK_VIDEO)
722                 {
723                         if(playable_tracks->is_playable(current_track, current_position, 1))
724                         {
725                                 playable_track = current_track;
726                                 total_playable_tracks++;
727                         }
728                 }
729         }
731 //printf("Render::direct_copy_possible 1 %d\n", result);
732         if(total_playable_tracks != 1) result = 0;
733 //printf("Render::direct_copy_possible 2 %d\n", result);
735 // Edit must have a source file
736         if(result)
737         {
738 //printf("Render::direct_copy_possible 3 %d\n", result);
739                 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
740 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
741                 if(!playable_edit)
742                         result = 0;
743         }
745 // Source file must be able to copy to destination file.
746 // Source file must be same size as project output.
747         if(result)
748         {
749 //printf("Render::direct_copy_possible 5 %d\n", result);
750                 if(!file->can_copy_from(playable_edit, 
751                         current_position + playable_track->nudge,
752                         edl->session->output_w, 
753                         edl->session->output_h))
754                         result = 0;
755         }
756 //printf("Render::direct_copy_possible 6 %d\n", result);
758 // Test conditions mutual between vrender.C and this.
759         if(result && 
760                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
761                 result = 0;
762 //printf("Render::direct_copy_possible 7 %d\n", result);
764         return result;
775 int PackageRenderer::get_master()
777         return 0;
780 // Get result status from server
781 int PackageRenderer::get_result()
783         return 0;
786 void PackageRenderer::set_result(int value)
790 void PackageRenderer::set_progress(int64_t value)
792 }       
794 int PackageRenderer::set_video_map(int64_t position, int value)
798 int PackageRenderer::progress_cancelled()
800         return 0;
801 }       
813 //      Local Variables:
814 //      mode: C++
815 //      c-file-style: "linux"
816 //      End: