r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / packagerenderer.C
blobbead5357ce72c31ded5d2d914748e16ab2fa99ac
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                 sprintf(asset->path, RENDERFARM_FS_PREFIX "%s", package->path);
138         else
139                 strcpy(asset->path, package->path);
143         
145         file = new File;
147         file->set_processors(preferences->processors);
149         result = file->open_file(plugindb, 
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 //printf("PackageRenderer::do_video 1\n");
324 // Do video data
325         if(asset->video_data)
326         {
327 // get the absolute video position from the audio position
328                 int64_t video_end = video_position + video_read_length;
330                 if(video_end > package->video_end)
331                         video_end = package->video_end;
333 //printf("PackageRenderer::do_video 1\n");
334                 while(video_position < video_end && !result)
335                 {
336 // Try to copy the compressed frame directly from the input to output files
337 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
338                         if(direct_frame_copy(command->get_edl(), 
339                                 video_position, 
340                                 file, 
341                                 result))
342                         {
343 // Direct frame copy failed.
344 // Switch back to background compression
345                                 if(direct_frame_copying)
346                                 {
347                                         file->start_video_thread(video_write_length, 
348                                                 command->get_edl()->session->color_model,
349                                                 preferences->processors > 1 ? 2 : 1,
350                                                 0);
351                                         direct_frame_copying = 0;
352                                 }
354 // Try to use the rendering engine to write the frame.
355 // Get a buffer for background writing.
358 //printf("PackageRenderer::do_video 3\n");
360                                 if(video_write_position == 0)
361                                         video_output = file->get_video_buffer();
365 //printf("PackageRenderer::do_video 4\n");
368 // Construct layered output buffer
369                                 for(int i = 0; i < MAX_CHANNELS; i++)
370                                         video_output_ptr[i] = 
371                                                 (i < asset->layers) ? 
372                                                         video_output[i][video_write_position] : 
373                                                         0;
374                                 result |= render_engine->vrender->process_buffer(
375                                         video_output_ptr, 
376                                         video_position, 
377                                         0);
380 //printf("PackageRenderer::do_video 5\n");
382                                 if(mwindow && video_device->output_visible())
383                                 {
384 // Vector for video device
385                                         VFrame *preview_output[MAX_CHANNELS];
387                                         video_device->new_output_buffers(preview_output,
388                                                 command->get_edl()->session->color_model);
390                                         for(int i = 0; i < MAX_CHANNELS; i++)
391                                                 if(preview_output[i])
392                                                         preview_output[i]->copy_from(video_output_ptr[i]);
393                                         video_device->write_buffer(preview_output, 
394                                                 command->get_edl());
395                                 }
398 //printf("PackageRenderer::do_video 6\n");
400 // Write to file
401                                 if(video_preroll)
402                                 {
403 //printf("PackageRenderer::do_video 6.1\n");
404                                         video_preroll--;
405 // Keep the write position at 0 until ready to write real frames
406                                         result |= file->write_video_buffer(0);
407 //printf("PackageRenderer::do_video 6.2\n");
408                                         video_write_position = 0;
409                                 }
410                                 else
411                                 {
412 //printf("PackageRenderer::do_video 7\n");
413 // Set background rendering parameters
414                                         if(package->use_brender)
415                                         {
416 // Allow us to skip sections of the output file by setting the frame number.
417                                                 video_output_ptr[0]->set_number(video_position);
418                                         }
419                                         video_write_position++;
420 //printf("PackageRenderer::do_video 8\n");
422                                         if(video_write_position >= video_write_length)
423                                         {
424 //printf("PackageRenderer::do_video 9\n");
425                                                 result |= file->write_video_buffer(video_write_position);
426 //printf("PackageRenderer::do_video 10\n");
427 // Update the brender map after writing the files.
428                                                 if(package->use_brender)
429                                                         for(int i = 0; i < video_write_position; i++)
430                                                                 set_video_map(video_position + 1 - video_write_position + i, 
431                                                                         BRender::RENDERED);
432                                                 video_write_position = 0;
433                                         }
434 //printf("PackageRenderer::do_video 11\n");
435                                 }
438                         }
440                         video_position++;
441                         if(get_result()) result = 1;
442                         if(!result && progress_cancelled()) result = 1;
443                 }
444         }
445         else
446         {
447                 video_position += video_read_length;
448         }
449 //printf("PackageRenderer::do_video 14 %d %d\n", video_position, result);
453 void PackageRenderer::stop_engine()
455         delete render_engine;
456         delete playable_tracks;
460 void PackageRenderer::stop_output()
462         if(asset->audio_data)
463         {
464 // stop file I/O
465                 file->stop_audio_thread();
466         }
468         if(asset->video_data)
469         {
470 //printf("PackageRenderer::stop_output 1\n");
471                 delete compressed_output;
472 //printf("PackageRenderer::stop_output 2\n");
473                 if(video_write_position)
474                         file->write_video_buffer(video_write_position);
475 //printf("PackageRenderer::stop_output 3\n");
476                 if(package->use_brender)
477                         for(int i = 0; i < video_write_position; i++)
478                                 set_video_map(video_position - video_write_position + i, 
479                                         BRender::RENDERED);
480 //printf("PackageRenderer::stop_output 4\n");
481                 video_write_position = 0;       
482                 file->stop_video_thread();
483 //printf("PackageRenderer::stop_output 5\n");
484                 if(mwindow)
485                 {
486                         video_device->stop_playback();
487                         video_device->close_all();
488                         delete video_device;
489                 }
490         }
494 void PackageRenderer::close_output()
496         if(mwindow)
497                 mwindow->sighandler->pull_file(file);
498         file->close_file();
499         delete file;
500         delete asset;
503 // Aborts and returns 1 if an error is encountered.
504 int PackageRenderer::render_package(RenderPackage *package)
506         int audio_done = 0;
507         int video_done = 0;
508         int samples_rendered = 0;
511         result = 0;
512         this->package = package;
514 // printf(
515 // "PackageRenderer::render_package: audio s=%lld l=%lld video s=%lld l=%lld\n",
516 //      package->audio_start, 
517 //      package->audio_end - package->audio_start, 
518 //      package->video_start, 
519 //      package->video_end - package->video_start);
522         create_output();
524         if(!asset->video_data) video_done = 1;
525         if(!asset->audio_data) audio_done = 1;
527 // Create render engine
528         if(!result)
529         {
530                 create_engine();
532 //printf("PackageRenderer::render_package 5 %d\n", result);
534 // Main loop
535                 while((!audio_done || !video_done) && !result)
536                 {
537                         int need_audio = 0, need_video = 0;
542 // Calculate lengths to process.  Audio fragment is constant.
543                         if(!audio_done)
544                         {
545                                 if(audio_position + audio_read_length >= package->audio_end)
546                                 {
547                                         audio_done = 1;
548                                         audio_read_length = package->audio_end - audio_position;
549                                 }
551                                 samples_rendered = audio_read_length;
552                                 need_audio = 1;
553                         }
555 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
557                         if(!video_done)
558                         {
559                                 if(audio_done)
560                                 {
561                                         video_read_length = package->video_end - video_position;
562 // Packetize video length so progress gets updated
563                                         video_read_length = (int)MIN(asset->frame_rate, video_read_length);
564                                         video_read_length = MAX(video_read_length, 30);
565                                 }
566                                 else
567 // Guide video with audio
568                                 {
569                                         video_read_length = Units::to_int64(
570                                                 (double)(audio_position + audio_read_length) / 
571                                                 asset->sample_rate * 
572                                                 asset->frame_rate) - 
573                                                 video_position;
574                                 }
576 // Clamp length
577                                 if(video_position + video_read_length >= package->video_end)
578                                 {
579                                         video_done = 1;
580                                         video_read_length = package->video_end - video_position;
581                                 }
583 // Calculate samples rendered for progress bar.
584                                 if(audio_done)
585                                         samples_rendered = Units::round((double)video_read_length /
586                                                 asset->frame_rate *
587                                                 asset->sample_rate);
589                                 need_video = 1;
590                         }
592 //printf("PackageRenderer::render_package 1 %d %lld %lld\n", result, audio_read_length, video_read_length);
593                         if(need_video && !result) do_video();
594 //printf("PackageRenderer::render_package 7 %d %d\n", result, samples_rendered);
595                         if(need_audio && !result) do_audio();
598                         if(!result) set_progress(samples_rendered);
604                         if(!result && progress_cancelled()) result = 1;
606 // printf("PackageRenderer::render_package 10 %d %d %d %d\n", 
607 // audio_read_length, video_read_length, samples_rendered, result);
608                         if(result) 
609                                 set_result(result);
610                         else
611                                 result = get_result();
612                 }
614 //printf("PackageRenderer::render_package 10\n");
615                 stop_engine();
616 //printf("PackageRenderer::render_package 11\n");
618                 stop_output();
619 //printf("PackageRenderer::render_package 12\n");
622         }
626 //printf("PackageRenderer::render_package 13\n");
627         close_output();
628 //printf("PackageRenderer::render_package 14\n");
631         set_result(result);
632 //printf("PackageRenderer::render_package 15\n");
636         return result;
646 // Try to copy the compressed frame directly from the input to output files
647 // Return 1 on failure and 0 on success
648 int PackageRenderer::direct_frame_copy(EDL *edl, 
649         int64_t &video_position, 
650         File *file,
651         int &error)
653         Track *playable_track;
654         Edit *playable_edit;
655         int64_t frame_size;
656         int result = 0;
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 // Don't background render this one
695                         if(package->use_brender)
696                                 set_video_map(video_position, BRender::SCANNED);
698                         if(!package->use_brender)
699                         {
700                                 VFrame ***temp_output = new VFrame**[1];
701                                 temp_output[0] = new VFrame*[1];
702                                 temp_output[0][0] = compressed_output;
703                                 error |= file->write_frames(temp_output, 1);
704                                 delete temp_output[0];
705                                 delete temp_output;
706                         }
707                 }
708                 return 0;
709         }
710         else
711                 return 1;
714 int PackageRenderer::direct_copy_possible(EDL *edl,
715                                 int64_t current_position, 
716                                 Track* playable_track,  // The one track which is playable
717                                 Edit* &playable_edit, // The edit which is playing
718                                 File *file)   // Output file
720         int result = 1;
721         int total_playable_tracks = 0;
722         Track* current_track;
723         Patch* current_patch;
724         Auto* current_auto;
725         int temp;
727 // Number of playable tracks must equal 1
728         for(current_track = edl->tracks->first;
729                 current_track && result; 
730                 current_track = current_track->next)
731         {
732                 if(current_track->data_type == TRACK_VIDEO)
733                 {
734                         if(playable_tracks->is_playable(current_track, current_position, 1))
735                         {
736                                 playable_track = current_track;
737                                 total_playable_tracks++;
738                         }
739                 }
740         }
742 //printf("Render::direct_copy_possible 1 %d\n", result);
743         if(total_playable_tracks != 1) result = 0;
744 //printf("Render::direct_copy_possible 2 %d\n", result);
746 // Edit must have a source file
747         if(result)
748         {
749 //printf("Render::direct_copy_possible 3 %d\n", result);
750                 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
751 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
752                 if(!playable_edit)
753                         result = 0;
754         }
756 // Source file must be able to copy to destination file.
757 // Source file must be same size as project output.
758         if(result)
759         {
760 //printf("Render::direct_copy_possible 5 %d\n", result);
761                 if(!file->can_copy_from(playable_edit, 
762                         current_position + playable_track->nudge,
763                         edl->session->output_w, 
764                         edl->session->output_h))
765                         result = 0;
766         }
767 //printf("Render::direct_copy_possible 6 %d\n", result);
769 // Test conditions mutual between vrender.C and this.
770         if(result && 
771                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
772                 result = 0;
773 //printf("Render::direct_copy_possible 7 %d\n", result);
775         return result;
788 // Get result status from server
789 int PackageRenderer::get_result()
791         return 0;
794 void PackageRenderer::set_result(int value)
798 void PackageRenderer::set_progress(int64_t value)
800 }       
802 void PackageRenderer::set_video_map(int64_t position, int value)
806 int PackageRenderer::progress_cancelled()
808         return 0;
809 }