r793: Small API addon, so plugins can 'see' camera and projector automation
[cinelerra_cv/mob.git] / cinelerra / packagerenderer.C
blobaa1f7fe0c17bb62f176e21bb6e5f0f5a53afb3a7
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;
82 int PackageRenderer::initialize(MWindow *mwindow,
83                 EDL *edl, 
84                 Preferences *preferences, 
85                 Asset *default_asset,
86                 ArrayList<PluginServer*> *plugindb)
88         int result = 0;
90         this->mwindow = mwindow;
91         this->edl = edl;
92         this->preferences = preferences;
93         this->default_asset = default_asset;
94         this->plugindb = plugindb;
97 //printf("PackageRenderer::initialize %d\n", preferences->processors);
98         command = new TransportCommand;
99         command->command = NORMAL_FWD;
100         command->get_edl()->copy_all(edl);
101         command->change_type = CHANGE_ALL;
102         command->set_playback_range(edl);
104         default_asset->frame_rate = command->get_edl()->session->frame_rate;
105         default_asset->sample_rate = command->get_edl()->session->sample_rate;
106         default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
107                 command->get_edl()->session->aspect_h;
108         result = Render::check_asset(edl, *default_asset);
110         audio_cache = new CICache(command->get_edl(), preferences, plugindb);
111         video_cache = new CICache(command->get_edl(), preferences, plugindb);
113         PlaybackConfig *config = command->get_edl()->session->playback_config;
114         aconfig = new AudioOutConfig(0);
115         vconfig = new VideoOutConfig;
116 //      playback_config = new PlaybackConfig(PLAYBACK_LOCALHOST, 0);
117         for(int i = 0; i < MAX_CHANNELS; i++)
118         {
119                 vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
120         }
123         return result;
126 void PackageRenderer::create_output()
128         FileSystem fs;
129         asset = new Asset(*default_asset);
135 // Tag output paths for VFS here.
136 //      if(!mwindow && preferences->renderfarm_vfs && preferences->use_renderfarm)
137         if(!get_master() && preferences->renderfarm_vfs && preferences->use_renderfarm)
138                 sprintf(asset->path, RENDERFARM_FS_PREFIX "%s", package->path);
139         else
140                 strcpy(asset->path, package->path);
143         
145         file = new File;
147         file->set_processors(preferences->processors);
149         result = file->open_file(preferences, 
150                                         asset, 
151                                         0, 
152                                         1, 
153                                         command->get_edl()->session->sample_rate, 
154                                         command->get_edl()->session->frame_rate);
155 //printf("PackageRenderer::create_output 10 %d\n", result);
157         if(result && mwindow)
158         {
159 // open failed
160                 char string[BCTEXTLEN];
161                 sprintf(string, _("Couldn't open %s"), asset->path);
162                 ErrorBox error(PROGRAM_NAME ": Error",
163                         mwindow->gui->get_abs_cursor_x(1),
164                         mwindow->gui->get_abs_cursor_y(1));
165                 error.create_objects(string);
166                 error.run_window();
167         }
168         else
169         if(mwindow)
170         {
171                 mwindow->sighandler->push_file(file);
172                 IndexFile::delete_index(preferences, asset);
173         }
174 //printf("PackageRenderer::create_output 100 %d\n", result);
177 void PackageRenderer::create_engine()
179         int current_achannel = 0, current_vchannel = 0;
180         audio_read_length = command->get_edl()->session->sample_rate;
182         aconfig->fragment_size = audio_read_length;
185         render_engine = new RenderEngine(0,
186                 preferences,
187                 command,
188                 0,
189                 plugindb,
190                 0);
191         render_engine->set_acache(audio_cache);
192         render_engine->set_vcache(video_cache);
193         render_engine->arm_command(command, current_achannel, current_vchannel);
195         if(package->use_brender)
196         {
197                 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
198                         default_asset->frame_rate *
199                         default_asset->sample_rate);
200                 video_preroll = preferences->brender_preroll;
201         }
202         else
203         {
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         video_position = package->video_start - video_preroll;
215 // Create output buffers
216         if(asset->audio_data)
217         {
218                 file->start_audio_thread(audio_read_length, 
219                         preferences->processors > 1 ? 2 : 1);
220         }
223         if(asset->video_data)
224         {
225                 compressed_output = new VFrame;
226 // The write length needs to correlate with the processor count because
227 // it is passed to the file handler which usually processes frames simultaneously.
228                 video_write_length = preferences->processors;
229                 video_write_position = 0;
230                 direct_frame_copying = 0;
233 //printf("PackageRenderer::create_engine 1\n");
234                 file->start_video_thread(video_write_length,
235                         command->get_edl()->session->color_model,
236                         preferences->processors > 1 ? 2 : 1,
237                         0);
240                 if(mwindow)
241                 {
242                         video_device = new VideoDevice;
243                         video_device->open_output(vconfig, 
244                                 command->get_edl()->session->frame_rate, 
245                                 command->get_edl()->session->output_w, 
246                                 command->get_edl()->session->output_h, 
247                                 mwindow->cwindow->gui->canvas,
248                                 0);
249                         video_device->start_playback();
250                 }
251         }
254         playable_tracks = new PlayableTracks(render_engine, 
255                 video_position, 
256                 TRACK_VIDEO,
257                 1);
264 void PackageRenderer::do_audio()
266 //printf("PackageRenderer::do_audio 1\n");
267 // Do audio data
268         if(asset->audio_data)
269         {
270                 audio_output = file->get_audio_buffer();
271 // Zero unused channels in output vector
272                 for(int i = 0; i < MAX_CHANNELS; i++)
273                         audio_output_ptr[i] = (i < asset->channels) ? 
274                                 audio_output[i] : 
275                                 0;
280 // Call render engine
281                 result = render_engine->arender->process_buffer(audio_output_ptr, 
282                         audio_read_length, 
283                         audio_position,
284                         0);
286 //printf("PackageRenderer::do_audio 3\n");
289 // Fix buffers for preroll
290                 int64_t output_length = audio_read_length;
291                 if(audio_preroll > 0)
292                 {
293                         if(audio_preroll >= output_length)
294                                 output_length = 0;
295                         else
296                         {
297                                 output_length -= audio_preroll;
298                                 for(int i = 0; i < MAX_CHANNELS; i++)
299                                 {
300                                         if(audio_output_ptr[i])
301                                                 for(int j = 0; j < output_length; j++)
302                                                 {
303                                                         audio_output_ptr[i][j] = audio_output_ptr[i][j + audio_read_length - output_length];
304                                                 }
305                                 }
306                         }
307 //printf("PackageRenderer::do_audio 4\n");
309                         audio_preroll -= audio_read_length;
310                 }
312 // Must perform writes even if 0 length so get_audio_buffer doesn't block
313                 result |= file->write_audio_buffer(output_length);
314         }
316         audio_position += audio_read_length;
317 //printf("PackageRenderer::do_audio 5\n");
321 void PackageRenderer::do_video()
323 // Do video data
324         if(asset->video_data)
325         {
326 // get the absolute video position from the audio position
327                 int64_t video_end = video_position + video_read_length;
329                 if(video_end > package->video_end)
330                         video_end = package->video_end;
332                 while(video_position < video_end && !result)
333                 {
334 // Try to copy the compressed frame directly from the input to output files
335 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
336                         if(direct_frame_copy(command->get_edl(), 
337                                 video_position, 
338                                 file, 
339                                 result))
340                         {
341 // Direct frame copy failed.
342 // Switch back to background compression
343                                 if(direct_frame_copying)
344                                 {
345                                         file->start_video_thread(video_write_length, 
346                                                 command->get_edl()->session->color_model,
347                                                 preferences->processors > 1 ? 2 : 1,
348                                                 0);
349                                         direct_frame_copying = 0;
350                                 }
352 // Try to use the rendering engine to write the frame.
353 // Get a buffer for background writing.
357                                 if(video_write_position == 0)
358                                         video_output = file->get_video_buffer();
364 // Construct layered output buffer
365                                 for(int i = 0; i < MAX_CHANNELS; i++)
366                                         video_output_ptr[i] = 
367                                                 (i < asset->layers) ? 
368                                                         video_output[i][video_write_position] : 
369                                                         0;
371                                 if(!result)
372                                         result = render_engine->vrender->process_buffer(
373                                                 video_output_ptr, 
374                                                 video_position, 
375                                                 0);
379                                 if(!result && 
380                                         mwindow && 
381                                         video_device->output_visible())
382                                 {
383 // Vector for video device
384                                         VFrame *preview_output[MAX_CHANNELS];
386                                         video_device->new_output_buffers(preview_output,
387                                                 command->get_edl()->session->color_model);
389                                         for(int i = 0; i < MAX_CHANNELS; i++)
390                                                 if(preview_output[i])
391                                                         preview_output[i]->copy_from(video_output_ptr[i]);
392                                         video_device->write_buffer(preview_output, 
393                                                 command->get_edl());
394                                 }
398 // Don't write to file
399                                 if(video_preroll && !result)
400                                 {
401                                         video_preroll--;
402 // Keep the write position at 0 until ready to write real frames
403                                         result = file->write_video_buffer(0);
404                                         video_write_position = 0;
405                                 }
406                                 else
407                                 if(!result)
408                                 {
409 //printf("PackageRenderer::do_video 7\n");
410 // Set background rendering parameters
411 //                                      if(package->use_brender)
412 //                                      {
413 // Allow us to skip sections of the output file by setting the frame number.
414 // Used by background render and render farm.
415                                                 video_output_ptr[0]->set_number(video_position);
416 //printf("PackageRenderer::do_video 8 %p %lld\n", video_output_ptr[0], video_position);
417 //                                      }
418                                         video_write_position++;
420                                         if(video_write_position >= video_write_length)
421                                         {
422 //printf("PackageRenderer::do_video 9\n");
423                                                 result = file->write_video_buffer(video_write_position);
424 // Update the brender map after writing the files.
425                                                 if(package->use_brender)
426                                                 {
427 //printf("PackageRenderer::do_video 10\n");
428                                                         for(int i = 0; i < video_write_position && !result; i++)
429                                                         {
430                                                                 result = set_video_map(video_position + 1 - video_write_position + i, 
431                                                                         BRender::RENDERED);
432                                                         }
433 //printf("PackageRenderer::do_video 11 %d\n", result);
434                                                 }
435                                                 video_write_position = 0;
436                                         }
437                                 }
440                         }
442                         video_position++;
443                         if(!result && get_result()) result = 1;
444                         if(!result && progress_cancelled()) result = 1;
445                 }
446         }
447         else
448         {
449                 video_position += video_read_length;
450         }
454 void PackageRenderer::stop_engine()
456         delete render_engine;
457         delete playable_tracks;
461 void PackageRenderer::stop_output()
463         int error = 0;
464         if(asset->audio_data)
465         {
466 // stop file I/O
467                 file->stop_audio_thread();
468         }
470         if(asset->video_data)
471         {
472                 delete compressed_output;
473                 if(video_write_position)
474                         file->write_video_buffer(video_write_position);
475                 if(package->use_brender)
476                 {
477                         for(int i = 0; i < video_write_position && !error; i++)
478                         {
479                                 error = set_video_map(video_position - video_write_position + i, 
480                                         BRender::RENDERED);
481                         }
482                 }
483                 video_write_position = 0;       
484                 if(!error) file->stop_video_thread();
485                 if(mwindow)
486                 {
487                         video_device->stop_playback();
488                         video_device->close_all();
489                         delete video_device;
490                 }
491         }
495 void PackageRenderer::close_output()
497         if(mwindow)
498                 mwindow->sighandler->pull_file(file);
499         file->close_file();
500         delete file;
501         delete asset;
504 // Aborts and returns 1 if an error is encountered.
505 int PackageRenderer::render_package(RenderPackage *package)
507         int audio_done = 0;
508         int video_done = 0;
509         int samples_rendered = 0;
512         result = 0;
513         this->package = package;
515 // printf(
516 // "PackageRenderer::render_package: audio s=%lld l=%lld video s=%lld l=%lld\n",
517 //      package->audio_start, 
518 //      package->audio_end - package->audio_start, 
519 //      package->video_start, 
520 //      package->video_end - package->video_start);
523         create_output();
525         if(!asset->video_data) video_done = 1;
526         if(!asset->audio_data) audio_done = 1;
528 // Create render engine
529         if(!result)
530         {
531                 create_engine();
533 //printf("PackageRenderer::render_package 5 %d\n", result);
535 // Main loop
536                 while((!audio_done || !video_done) && !result)
537                 {
538                         int need_audio = 0, need_video = 0;
543 // Calculate lengths to process.  Audio fragment is constant.
544                         if(!audio_done)
545                         {
546                                 if(audio_position + audio_read_length >= package->audio_end)
547                                 {
548                                         audio_done = 1;
549                                         audio_read_length = package->audio_end - audio_position;
550                                 }
552                                 samples_rendered = audio_read_length;
553                                 need_audio = 1;
554                         }
556 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
558                         if(!video_done)
559                         {
560                                 if(audio_done)
561                                 {
562                                         video_read_length = package->video_end - video_position;
563 // Packetize video length so progress gets updated
564                                         video_read_length = (int)MIN(asset->frame_rate, video_read_length);
565                                         video_read_length = MAX(video_read_length, 30);
566                                 }
567                                 else
568 // Guide video with audio
569                                 {
570                                         video_read_length = Units::to_int64(
571                                                 (double)(audio_position + audio_read_length) / 
572                                                 asset->sample_rate * 
573                                                 asset->frame_rate) - 
574                                                 video_position;
575                                 }
577 // Clamp length
578                                 if(video_position + video_read_length >= package->video_end)
579                                 {
580                                         video_done = 1;
581                                         video_read_length = package->video_end - video_position;
582                                 }
584 // Calculate samples rendered for progress bar.
585                                 if(audio_done)
586                                         samples_rendered = Units::round((double)video_read_length /
587                                                 asset->frame_rate *
588                                                 asset->sample_rate);
590                                 need_video = 1;
591                         }
593 //printf("PackageRenderer::render_package 1 %d %lld %lld\n", result, audio_read_length, video_read_length);
594                         if(need_video && !result) do_video();
595 //printf("PackageRenderer::render_package 7 %d %d\n", result, samples_rendered);
596                         if(need_audio && !result) do_audio();
599                         if(!result) set_progress(samples_rendered);
605                         if(!result && progress_cancelled()) result = 1;
607 // printf("PackageRenderer::render_package 10 %d %d %d %d\n", 
608 // audio_read_length, video_read_length, samples_rendered, result);
609                         if(result) 
610                                 set_result(result);
611                         else
612                                 result = get_result();
613                 }
615 //printf("PackageRenderer::render_package 20\n");
616                 stop_engine();
617 //printf("PackageRenderer::render_package 30\n");
619                 stop_output();
620 //printf("PackageRenderer::render_package 40\n");
623         }
627 //printf("PackageRenderer::render_package 50\n");
628         close_output();
629 //printf("PackageRenderer::render_package 60\n");
632         set_result(result);
633 //printf("PackageRenderer::render_package 70\n");
637         return result;
647 // Try to copy the compressed frame directly from the input to output files
648 // Return 1 on failure and 0 on success
649 int PackageRenderer::direct_frame_copy(EDL *edl, 
650         int64_t &video_position, 
651         File *file,
652         int &error)
654         Track *playable_track;
655         Edit *playable_edit;
656         int64_t frame_size;
658 //printf("Render::direct_frame_copy 1\n");
659         if(direct_copy_possible(edl, 
660                 video_position, 
661                 playable_track, 
662                 playable_edit, 
663                 file))
664         {
665 // Switch to direct copying
666                 if(!direct_frame_copying)
667                 {
668                         if(video_write_position)
669                         {
670                                 error |= file->write_video_buffer(video_write_position);
671                                 video_write_position = 0;
672                         }
673                         file->stop_video_thread();
674                         direct_frame_copying = 1;
675                 }
676 //printf("Render::direct_frame_copy 2\n");
678                 if(!package->use_brender)
679                         error |= ((VEdit*)playable_edit)->read_frame(compressed_output, 
680                                 video_position,
681                                 PLAY_FORWARD,
682                                 video_cache,
683                                 1,
684                                 0);
687                 if(!error && video_preroll > 0)
688                 {
689                         video_preroll--;
690                 }
691                 else
692                 if(!error)
693                 {
694                         if(package->use_brender)
695                         {
696 //printf("PackageRenderer::direct_frame_copy 1\n");
697                                 error = set_video_map(video_position, BRender::SCANNED);
698 //printf("PackageRenderer::direct_frame_copy 10 %d\n", error);
699                         }
700                         else
701                         {
702                                 VFrame ***temp_output = new VFrame**[1];
703                                 temp_output[0] = new VFrame*[1];
704                                 temp_output[0][0] = compressed_output;
705                                 error = file->write_frames(temp_output, 1);
706                                 delete temp_output[0];
707                                 delete temp_output;
708                         }
709                 }
710                 return 0;
711         }
712         else
713                 return 1;
716 int PackageRenderer::direct_copy_possible(EDL *edl,
717                                 int64_t current_position, 
718                                 Track* playable_track,  // The one track which is playable
719                                 Edit* &playable_edit, // The edit which is playing
720                                 File *file)   // Output file
722         int result = 1;
723         int total_playable_tracks = 0;
724         Track* current_track;
725         Patch* current_patch;
726         Auto* current_auto;
727         int temp;
729 // Number of playable tracks must equal 1
730         for(current_track = edl->tracks->first;
731                 current_track && result; 
732                 current_track = current_track->next)
733         {
734                 if(current_track->data_type == TRACK_VIDEO)
735                 {
736                         if(playable_tracks->is_playable(current_track, current_position, 1))
737                         {
738                                 playable_track = current_track;
739                                 total_playable_tracks++;
740                         }
741                 }
742         }
744 //printf("Render::direct_copy_possible 1 %d\n", result);
745         if(total_playable_tracks != 1) result = 0;
746 //printf("Render::direct_copy_possible 2 %d\n", result);
748 // Edit must have a source file
749         if(result)
750         {
751 //printf("Render::direct_copy_possible 3 %d\n", result);
752                 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
753 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
754                 if(!playable_edit)
755                         result = 0;
756         }
758 // Source file must be able to copy to destination file.
759 // Source file must be same size as project output.
760         if(result)
761         {
762 //printf("Render::direct_copy_possible 5 %d\n", result);
763                 if(!file->can_copy_from(playable_edit, 
764                         current_position + playable_track->nudge,
765                         edl->session->output_w, 
766                         edl->session->output_h))
767                         result = 0;
768         }
769 //printf("Render::direct_copy_possible 6 %d\n", result);
771 // Test conditions mutual between vrender.C and this.
772         if(result && 
773                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
774                 result = 0;
775 //printf("Render::direct_copy_possible 7 %d\n", result);
777         return result;
788 int PackageRenderer::get_master()
790         return 0;
793 // Get result status from server
794 int PackageRenderer::get_result()
796         return 0;
799 void PackageRenderer::set_result(int value)
803 void PackageRenderer::set_progress(int64_t value)
805 }       
807 int PackageRenderer::set_video_map(int64_t position, int value)
811 int PackageRenderer::progress_cancelled()
813         return 0;
814 }