r903: BC_FileBoxDirectoryText::handle_event - fix for the change in meaning of is_di...
[cinelerra_cv/mob.git] / cinelerra / packagerenderer.C
blob0ecf7a23ded1331a19c31ed5e680244c9a97d2d0
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 // PackageRenderer::initialize happens only once for every node when doing rendering session
83 // This is not called for each package!
85 int PackageRenderer::initialize(MWindow *mwindow,
86                 EDL *edl, 
87                 Preferences *preferences, 
88                 Asset *default_asset,
89                 ArrayList<PluginServer*> *plugindb)
91         int result = 0;
93         this->mwindow = mwindow;
94         this->edl = edl;
95         this->preferences = preferences;
96         this->default_asset = default_asset;
97         this->plugindb = plugindb;
100 //printf("PackageRenderer::initialize %d\n", preferences->processors);
101         command = new TransportCommand;
102         command->command = NORMAL_FWD;
103         command->get_edl()->copy_all(edl);
104         command->change_type = CHANGE_ALL;
105         command->set_playback_range(edl);
107         default_asset->frame_rate = command->get_edl()->session->frame_rate;
108         default_asset->sample_rate = command->get_edl()->session->sample_rate;
109         default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
110                 command->get_edl()->session->aspect_h;
111         result = Render::check_asset(edl, *default_asset);
113         audio_cache = new CICache(preferences, plugindb);
114         video_cache = new CICache(preferences, plugindb);
116         PlaybackConfig *config = command->get_edl()->session->playback_config;
117         aconfig = new AudioOutConfig(0);
118         vconfig = new VideoOutConfig;
120         return result;
123 void PackageRenderer::create_output()
125         FileSystem fs;
126         asset = new Asset(*default_asset);
132         strcpy(asset->path, package->path);
135         
137         file = new File;
139         file->set_processors(preferences->processors);
141         result = file->open_file(preferences, 
142                                         asset, 
143                                         0, 
144                                         1, 
145                                         command->get_edl()->session->sample_rate, 
146                                         command->get_edl()->session->frame_rate);
147 //printf("PackageRenderer::create_output 10 %d\n", result);
149         if(result && mwindow)
150         {
151 // open failed
152                 char string[BCTEXTLEN];
153                 sprintf(string, _("Couldn't open %s"), asset->path);
154                 ErrorBox error(PROGRAM_NAME ": Error",
155                         mwindow->gui->get_abs_cursor_x(1),
156                         mwindow->gui->get_abs_cursor_y(1));
157                 error.create_objects(string);
158                 error.run_window();
159         }
160         else
161         if(mwindow)
162         {
163                 mwindow->sighandler->push_file(file);
164                 IndexFile::delete_index(preferences, asset);
165         }
166 //printf("PackageRenderer::create_output 100 %d\n", result);
169 void PackageRenderer::create_engine()
171         int current_achannel = 0, current_vchannel = 0;
172         audio_read_length = command->get_edl()->session->sample_rate;
174         aconfig->fragment_size = audio_read_length;
177         render_engine = new RenderEngine(0,
178                 preferences,
179                 command,
180                 0,
181                 plugindb,
182                 0);
183         render_engine->set_acache(audio_cache);
184         render_engine->set_vcache(video_cache);
185         render_engine->arm_command(command, current_achannel, current_vchannel);
187         if(package->use_brender)
188         {
189                 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
190                         default_asset->frame_rate *
191                         default_asset->sample_rate);
192                 video_preroll = preferences->brender_preroll;
193         }
194         else
195         {
196                 audio_preroll = Units::to_int64(preferences->render_preroll * 
197                         default_asset->sample_rate);
198                 video_preroll = Units::to_int64(preferences->render_preroll * 
199                         default_asset->frame_rate);
200         }
201         audio_position = package->audio_start - audio_preroll;
202         video_position = package->video_start - video_preroll;
207 // Create output buffers
208         if(asset->audio_data)
209         {
210                 file->start_audio_thread(audio_read_length, 
211                         preferences->processors > 1 ? 2 : 1);
212         }
215         if(asset->video_data)
216         {
217                 compressed_output = new VFrame;
218 // The write length needs to correlate with the processor count because
219 // it is passed to the file handler which usually processes frames simultaneously.
220                 video_write_length = preferences->processors;
221                 video_write_position = 0;
222                 direct_frame_copying = 0;
225 //printf("PackageRenderer::create_engine 1\n");
226                 file->start_video_thread(video_write_length,
227                         command->get_edl()->session->color_model,
228                         preferences->processors > 1 ? 2 : 1,
229                         0);
232                 if(mwindow)
233                 {
234                         video_device = new VideoDevice;
235                         video_device->open_output(vconfig, 
236                                 command->get_edl()->session->frame_rate, 
237                                 command->get_edl()->session->output_w, 
238                                 command->get_edl()->session->output_h, 
239                                 mwindow->cwindow->gui->canvas,
240                                 0);
241                         video_device->start_playback();
242                 }
243         }
246         playable_tracks = new PlayableTracks(render_engine, 
247                 video_position, 
248                 TRACK_VIDEO,
249                 1);
256 void PackageRenderer::do_audio()
258 //printf("PackageRenderer::do_audio 1\n");
259 // Do audio data
260         if(asset->audio_data)
261         {
262                 audio_output = file->get_audio_buffer();
263 // Zero unused channels in output vector
264                 for(int i = 0; i < MAX_CHANNELS; i++)
265                         audio_output_ptr[i] = (i < asset->channels) ? 
266                                 audio_output[i] : 
267                                 0;
272 // Call render engine
273                 result = render_engine->arender->process_buffer(audio_output_ptr, 
274                         audio_read_length, 
275                         audio_position,
276                         0);
278 //printf("PackageRenderer::do_audio 3\n");
281 // Fix buffers for preroll
282                 int64_t output_length = audio_read_length;
283                 if(audio_preroll > 0)
284                 {
285                         if(audio_preroll >= output_length)
286                                 output_length = 0;
287                         else
288                         {
289                                 output_length -= audio_preroll;
290                                 for(int i = 0; i < MAX_CHANNELS; i++)
291                                 {
292                                         if(audio_output_ptr[i])
293                                                 for(int j = 0; j < output_length; j++)
294                                                 {
295                                                         audio_output_ptr[i][j] = audio_output_ptr[i][j + audio_read_length - output_length];
296                                                 }
297                                 }
298                         }
299 //printf("PackageRenderer::do_audio 4\n");
301                         audio_preroll -= audio_read_length;
302                 }
304 // Must perform writes even if 0 length so get_audio_buffer doesn't block
305                 result |= file->write_audio_buffer(output_length);
306         }
308         audio_position += audio_read_length;
309 //printf("PackageRenderer::do_audio 5\n");
313 void PackageRenderer::do_video()
315 // Do video data
316         if(asset->video_data)
317         {
318 // get the absolute video position from the audio position
319                 int64_t video_end = video_position + video_read_length;
321                 if(video_end > package->video_end)
322                         video_end = package->video_end;
324                 while(video_position < video_end && !result)
325                 {
326 // Try to copy the compressed frame directly from the input to output files
327 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
328                         if(direct_frame_copy(command->get_edl(), 
329                                 video_position, 
330                                 file, 
331                                 result))
332                         {
333 // Direct frame copy failed.
334 // Switch back to background compression
335                                 if(direct_frame_copying)
336                                 {
337                                         file->start_video_thread(video_write_length, 
338                                                 command->get_edl()->session->color_model,
339                                                 preferences->processors > 1 ? 2 : 1,
340                                                 0);
341                                         direct_frame_copying = 0;
342                                 }
344 // Try to use the rendering engine to write the frame.
345 // Get a buffer for background writing.
349                                 if(video_write_position == 0)
350                                         video_output = file->get_video_buffer();
356 // Construct layered output buffer
357                                 video_output_ptr = video_output[0][video_write_position];
359                                 if(!result)
360                                         result = render_engine->vrender->process_buffer(
361                                                 video_output_ptr, 
362                                                 video_position, 
363                                                 0);
367                                 if(!result && 
368                                         mwindow && 
369                                         video_device->output_visible())
370                                 {
371 // Vector for video device
372                                         VFrame *preview_output;
374                                         video_device->new_output_buffer(&preview_output,
375                                                 command->get_edl()->session->color_model);
377                                         preview_output->copy_from(video_output_ptr);
378                                         video_device->write_buffer(preview_output, 
379                                                 command->get_edl());
380                                 }
384 // Don't write to file
385                                 if(video_preroll && !result)
386                                 {
387                                         video_preroll--;
388 // Keep the write position at 0 until ready to write real frames
389                                         result = file->write_video_buffer(0);
390                                         video_write_position = 0;
391                                 }
392                                 else
393                                 if(!result)
394                                 {
395 // Set background rendering parameters
396 // Allow us to skip sections of the output file by setting the frame number.
397 // Used by background render and render farm.
398                                         video_output_ptr->set_number(video_position);
399                                         video_write_position++;
401                                         if(video_write_position >= video_write_length)
402                                         {
403 //printf("PackageRenderer::do_video 9\n");
404                                                 result = file->write_video_buffer(video_write_position);
405 // Update the brender map after writing the files.
406                                                 if(package->use_brender)
407                                                 {
408 //printf("PackageRenderer::do_video 10\n");
409                                                         for(int i = 0; i < video_write_position && !result; i++)
410                                                         {
411                                                                 result = set_video_map(video_position + 1 - video_write_position + i, 
412                                                                         BRender::RENDERED);
413                                                         }
414 //printf("PackageRenderer::do_video 11 %d\n", result);
415                                                 }
416                                                 video_write_position = 0;
417                                         }
418                                 }
421                         }
423                         video_position++;
424                         if(!result && get_result()) result = 1;
425                         if(!result && progress_cancelled()) result = 1;
426                 }
427         }
428         else
429         {
430                 video_position += video_read_length;
431         }
435 void PackageRenderer::stop_engine()
437         delete render_engine;
438         delete playable_tracks;
442 void PackageRenderer::stop_output()
444         int error = 0;
445         if(asset->audio_data)
446         {
447 // stop file I/O
448                 file->stop_audio_thread();
449         }
451         if(asset->video_data)
452         {
453                 delete compressed_output;
454                 if(video_write_position)
455                         file->write_video_buffer(video_write_position);
456                 if(package->use_brender)
457                 {
458                         for(int i = 0; i < video_write_position && !error; i++)
459                         {
460                                 error = set_video_map(video_position - video_write_position + i, 
461                                         BRender::RENDERED);
462                         }
463                 }
464                 video_write_position = 0;       
465                 if(!error) file->stop_video_thread();
466                 if(mwindow)
467                 {
468                         video_device->stop_playback();
469                         video_device->close_all();
470                         delete video_device;
471                 }
472         }
476 void PackageRenderer::close_output()
478         if(mwindow)
479                 mwindow->sighandler->pull_file(file);
480         file->close_file();
481         delete file;
482         Garbage::delete_object(asset);
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 }