r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / packagerenderer.C
blob9ba4c3bb135760494ebf4bf3b2af37a4775dabaf
1 #include "arender.h"
2 #include "assets.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 "mwindow.h"
18 #include "mwindowgui.h"
19 #include "packagerenderer.h"
20 #include "playabletracks.h"
21 #include "playbackconfig.h"
22 #include "pluginserver.h"
23 #include "preferences.h"
24 #include "render.h"
25 #include "renderengine.h"
26 #include "renderfarmfsserver.h"
27 #include "sighandler.h"
28 #include "tracks.h"
29 #include "transportque.h"
30 #include "vedit.h"
31 #include "vframe.h"
32 #include "videodevice.h"
33 #include "vrender.h"
35 #include <libintl.h>
36 #define _(String) gettext(String)
37 #define gettext_noop(String) String
38 #define N_(String) gettext_noop (String)
45 RenderPackage::RenderPackage()
47         audio_start = 0;
48         audio_end = 0;
49         video_start = 0;
50         video_end = 0;
51         path[0] = 0;
52         done = 0;
53         use_brender = 0;
56 RenderPackage::~RenderPackage()
67 // Used by RenderFarm and in the future, Render, to do packages.
68 PackageRenderer::PackageRenderer()
72 PackageRenderer::~PackageRenderer()
74         delete command;
75         delete audio_cache;
76         delete video_cache;
77 //      delete playback_config;
78         delete vconfig;
81 int PackageRenderer::initialize(MWindow *mwindow,
82                 EDL *edl, 
83                 Preferences *preferences, 
84                 Asset *default_asset,
85                 ArrayList<PluginServer*> *plugindb)
87         int result = 0;
89 //printf("PackageRenderer::initialize 1\n");
90         this->mwindow = mwindow;
91         this->edl = edl;
92         this->preferences = preferences;
93         this->default_asset = default_asset;
94         this->plugindb = plugindb;
95 //printf("PackageRenderer::initialize 1\n");
97         command = new TransportCommand;
98         command->command = NORMAL_FWD;
99         *command->get_edl() = *edl;
100         command->change_type = CHANGE_ALL;
101         command->set_playback_range(edl);
103         default_asset->frame_rate = command->get_edl()->session->frame_rate;
104         default_asset->sample_rate = command->get_edl()->session->sample_rate;
105         Render::check_asset(edl, *default_asset);
106 //printf("PackageRenderer::initialize 1 interpolation_type=%d\n",
107 //      command->get_edl()->session->interpolation_type);
109         audio_cache = new CICache(command->get_edl(), preferences, plugindb);
110         video_cache = new CICache(command->get_edl(), preferences, plugindb);
111 //printf("PackageRenderer::initialize 1\n");
113         vconfig = new VideoOutConfig(PLAYBACK_LOCALHOST, 0);
114 //      playback_config = new PlaybackConfig(PLAYBACK_LOCALHOST, 0);
115         for(int i = 0; i < MAX_CHANNELS; i++)
116         {
117                 vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
118 //              playback_config->vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
119 //              playback_config->aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
120         }
122 //printf("PackageRenderer::initialize 2\n");
124         return result;
127 void PackageRenderer::create_output()
129         FileSystem fs;
130         asset = new Asset(*default_asset);
134 //printf("PackageRenderer::create_output 1\n");
137 // Tag output paths for VFS here.
138         if(!mwindow && preferences->renderfarm_vfs)
139                 sprintf(asset->path, RENDERFARM_FS_PREFIX "%s", package->path);
140         else
141                 strcpy(asset->path, package->path);
145 //      if(mwindow)
146 //              strcpy(asset->path, package->path);
147 //      else
148 //              fs.join_names(asset->path, preferences->renderfarm_mountpoint, package->path);
149 //asset->dump();
150         
152 //printf("PackageRenderer::create_output 2\n");
153         file = new File;
155 //printf("PackageRenderer::create_output 3\n");
156         file->set_processors(command->get_edl()->session->smp + 1);
157 //printf("PackageRenderer::create_output 4 %s\n", asset->path);
159         result = file->open_file(plugindb, 
160                                         asset, 
161                                         0, 
162                                         1, 
163                                         command->get_edl()->session->sample_rate, 
164                                         command->get_edl()->session->frame_rate);
165 //printf("PackageRenderer::create_output 5\n");
167         if(result && mwindow)
168         {
169 // open failed
170                 char string[BCTEXTLEN];
171 //printf("PackageRenderer::create_output 6\n");
172                 sprintf(string, _("Couldn't open %s"), asset->path);
173 //printf("PackageRenderer::create_output 7\n");
174                 ErrorBox error(PROGRAM_NAME ": Error",
175                         mwindow->gui->get_abs_cursor_x(),
176                         mwindow->gui->get_abs_cursor_y());
177                 error.create_objects(string);
178                 error.run_window();
179         }
180         else
181         if(mwindow)
182         {
183                 mwindow->sighandler->push_file(file);
184 //printf("PackageRenderer::create_output 8\n");
185                 IndexFile::delete_index(preferences, asset);
186 //printf("PackageRenderer::create_output 9\n");
187         }
188 //printf("PackageRenderer::create_output 10\n");
191 void PackageRenderer::create_engine()
193         int current_achannel = 0, current_vchannel = 0;
194         audio_read_length = command->get_edl()->session->sample_rate;
196 //printf("PackageRenderer::create_engine 1\n");
197         command->get_edl()->session->audio_module_fragment = 
198                 command->get_edl()->session->audio_read_length = 
199                 audio_read_length;
202 //printf("PackageRenderer::create_engine 1\n");
203         render_engine = new RenderEngine(0,
204                 preferences,
205                 command,
206                 0,
207                 plugindb,
208                 0,
209                 0);
210 //printf("PackageRenderer::create_engine 1\n");
211         render_engine->set_acache(audio_cache);
212 //printf("PackageRenderer::create_engine 1\n");
213         render_engine->set_vcache(video_cache);
214 //printf("PackageRenderer::create_engine 1\n");
215         render_engine->arm_command(command, current_achannel, current_vchannel);
216 //printf("PackageRenderer::create_engine 1\n");
218         if(package->use_brender)
219         {
220                 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
221                         default_asset->frame_rate *
222                         default_asset->sample_rate);
223                 video_preroll = preferences->brender_preroll;
224         }
225         else
226         {
227                 audio_preroll = Units::to_int64(preferences->render_preroll * 
228                         default_asset->sample_rate);
229                 video_preroll = Units::to_int64(preferences->render_preroll * 
230                         default_asset->frame_rate);
231         }
232         audio_position = package->audio_start - audio_preroll;
233         video_position = package->video_start - video_preroll;
238 // Create output buffers
239         if(asset->audio_data)
240         {
241                 file->start_audio_thread(audio_read_length, 
242                         command->get_edl()->session->smp ? 2 : 1);
243         }
246         if(asset->video_data)
247         {
248                 compressed_output = new VFrame;
249                 video_write_length = command->get_edl()->session->smp + 1;
250                 video_write_position = 0;
251                 direct_frame_copying = 0;
254                 file->start_video_thread(video_write_length,
255                         command->get_edl()->session->color_model,
256                         command->get_edl()->session->smp ? 2 : 1,
257                         0);
260                 if(mwindow)
261                 {
262                         video_device = new VideoDevice;
263                         video_device->open_output(vconfig, 
264                                 command->get_edl()->session->frame_rate, 
265                                 command->get_edl()->session->output_w, 
266                                 command->get_edl()->session->output_h, 
267                                 mwindow->cwindow->gui->canvas,
268                                 0);
269 //printf("Render 14\n");
270                         video_device->start_playback();
271                 }
272         }
275         playable_tracks = new PlayableTracks(render_engine, 
276                 video_position, 
277                 TRACK_VIDEO);
284 void PackageRenderer::do_audio()
286 // Do audio data
287         if(asset->audio_data)
288         {
289                 audio_output = file->get_audio_buffer();
290 //printf("PackageRenderer::do_audio 1\n");
291 // Zero unused channels in output vector
292                 for(int i = 0; i < MAX_CHANNELS; i++)
293                         audio_output_ptr[i] = (i < asset->channels) ? 
294                                 audio_output[i] : 
295                                 0;
299 //printf("PackageRenderer::do_audio 2 %d %d\n", audio_read_length, audio_position);
301 // Call render engine
302                 result = render_engine->arender->process_buffer(audio_output_ptr, 
303                         audio_read_length, 
304                         audio_position,
305                         0);
307 //printf("PackageRenderer::do_audio 3\n");
310 // Fix buffers for preroll
311                 int64_t output_length = audio_read_length;
312                 if(audio_preroll > 0)
313                 {
314                         if(audio_preroll >= output_length)
315                                 output_length = 0;
316                         else
317                         {
318                                 output_length -= audio_preroll;
319                                 for(int i = 0; i < MAX_CHANNELS; i++)
320                                 {
321                                         if(audio_output_ptr[i])
322                                                 for(int j = 0; j < output_length; j++)
323                                                 {
324                                                         audio_output_ptr[i][j] = audio_output_ptr[i][j + audio_read_length - output_length];
325                                                 }
326                                 }
327                         }
328 //printf("PackageRenderer::do_audio 4\n");
330                         audio_preroll -= audio_read_length;
331                 }
333 // Must perform writes even if 0 length so get_audio_buffer doesn't block
334                 result |= file->write_audio_buffer(output_length);
335 //printf("PackageRenderer::do_audio 5\n");
336         }
338         audio_position += audio_read_length;
342 void PackageRenderer::do_video()
344 //printf("PackageRenderer::do_video 1\n");
345 // Do video data
346         if(asset->video_data)
347         {
348 // get the absolute video position from the audio position
349                 int64_t video_end = video_position + video_read_length;
351                 if(video_end > package->video_end)
352                         video_end = package->video_end;
354 //printf("PackageRenderer::do_video 1\n");
355                 while(video_position < video_end && !result)
356                 {
357 // Try to copy the compressed frame directly from the input to output files
358 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
359                         if(direct_frame_copy(command->get_edl(), 
360                                 video_position, 
361                                 file, 
362                                 result))
363                         {
364 // Direct frame copy failed.
365 //printf("PackageRenderer::do_video 3\n");
366 // Switch back to background compression
367                                 if(direct_frame_copying)
368                                 {
369                                         file->start_video_thread(video_write_length, 
370                                                 command->get_edl()->session->color_model,
371                                                 command->get_edl()->session->smp ? 2 : 1,
372                                                 0);
373                                         direct_frame_copying = 0;
374                                 }
376 //printf("PackageRenderer::do_video 4\n");
377 // Try to use the rendering engine to write the frame.
378 // Get a buffer for background writing.
382                                 if(video_write_position == 0)
383                                         video_output = file->get_video_buffer();
389 //printf("PackageRenderer::do_video 5\n");
390 // Construct layered output buffer
391                                 for(int i = 0; i < MAX_CHANNELS; i++)
392                                         video_output_ptr[i] = 
393                                                 (i < asset->layers) ? 
394                                                         video_output[i][video_write_position] : 
395                                                         0;
396 //printf("PackageRenderer::do_video 6\n");
397                                 result |= render_engine->vrender->process_buffer(
398                                         video_output_ptr, 
399                                         video_position, 
400                                         0);
403 //printf("PackageRenderer::do_video 7\n");
405                                 if(mwindow && video_device->output_visible())
406                                 {
407 // Vector for video device
408                                         VFrame *preview_output[MAX_CHANNELS];
410                                         video_device->new_output_buffers(preview_output,
411                                                 command->get_edl()->session->color_model);
412 //printf("PackageRenderer::do_video 8\n");
414                                         for(int i = 0; i < MAX_CHANNELS; i++)
415                                                 if(preview_output[i])
416                                                         preview_output[i]->copy_from(video_output_ptr[i]);
417 //printf("PackageRenderer::do_video 9\n");
418                                         video_device->write_buffer(preview_output, 
419                                                 command->get_edl());
420 //printf("PackageRenderer::do_video 10\n");
421                                 }
425 // Write to file
426                                 if(video_preroll)
427                                 {
428                                         video_preroll--;
429 // Keep the write position at 0 until ready to write real frames
430                                         result |= file->write_video_buffer(0);
431                                         video_write_position = 0;
432                                 }
433                                 else
434                                 {
435 // Set background rendering parameters
436                                         if(package->use_brender)
437                                         {
438 // Allow us to skip sections of the output file by setting the frame number.
439                                                 video_output_ptr[0]->set_number(video_position);
440                                         }
441                                         video_write_position++;
443                                         if(video_write_position >= video_write_length)
444                                         {
445                                                 result |= file->write_video_buffer(video_write_position);
446 // Update the brender map after writing the files.
447 //printf("PackageRenderer::do_video 12 %d %d\n", package->use_brender, video_write_position);
448                                                 if(package->use_brender)
449                                                         for(int i = 0; i < video_write_position; i++)
450                                                                 set_video_map(video_position + 1 - video_write_position + i, 
451                                                                         BRender::RENDERED);
452                                                 video_write_position = 0;
453                                         }
454                                 }
457                         }
459                         video_position++;
460 //printf("PackageRenderer::do_video 12\n");
461                         if(get_result()) result = 1;
462 //printf("PackageRenderer::do_video 13 %d %d\n", video_position, result);
463                         if(!result && progress_cancelled()) result = 1;
464 //printf("PackageRenderer::do_video 14 %d %d\n", video_position, result);
465                 }
466         }
467         else
468         {
469                 video_position += video_read_length;
470         }
474 void PackageRenderer::stop_engine()
476         delete render_engine;
477         delete playable_tracks;
481 void PackageRenderer::stop_output()
483         if(asset->audio_data)
484         {
485 // stop file I/O
486                 file->stop_audio_thread();
487         }
489         if(asset->video_data)
490         {
491                 delete compressed_output;
492                 if(video_write_position)
493                         file->write_video_buffer(video_write_position);
494                 if(package->use_brender)
495                         for(int i = 0; i < video_write_position; i++)
496                                 set_video_map(video_position - video_write_position + i, 
497                                         BRender::RENDERED);
498                 video_write_position = 0;       
499                 file->stop_video_thread();
500                 if(mwindow)
501                 {
502                         video_device->stop_playback();
503                         video_device->close_all();
504                         delete video_device;
505                 }
506         }
510 void PackageRenderer::close_output()
512 //printf("PackageRenderer::close_output 1\n");
513         if(mwindow)
514                 mwindow->sighandler->pull_file(file);
515         file->close_file();
516 //printf("PackageRenderer::close_output 1\n");
517         delete file;
518 //printf("PackageRenderer::close_output 1\n");
519         delete asset;
520 //printf("PackageRenderer::close_output 2\n");
523 // Aborts and returns 1 if an error is encountered.
524 int PackageRenderer::render_package(RenderPackage *package)
526         int audio_done = 0;
527         int video_done = 0;
528         int samples_rendered = 0;
530         result = 0;
531         this->package = package;
533 // printf(
534 // "PackageRenderer::render_package: audio s=%d l=%d video s=%d l=%d\n",
535 //      package->audio_start, 
536 //      package->audio_end - package->audio_start, 
537 //      package->video_start, 
538 //      package->video_end - package->video_start);
540 //printf("PackageRenderer::render_package 1\n");
542         create_output();
543 //printf("PackageRenderer::render_package 2\n");
546 // Create render engine
547         if(!result)
548         {
549                 create_engine();
551 //printf("PackageRenderer::render_package 5\n");
552 // Main loop
553                 while((!audio_done || !video_done) && !result)
554                 {
555                         int need_audio = 0, need_video = 0;
560 // Calculate lengths to process
561                         if(!audio_done)
562                         {
563                                 if(audio_position + audio_read_length >= package->audio_end)
564                                 {
565                                         audio_done = 1;
566                                         audio_read_length = package->audio_end - audio_position;
567                                 }
569                                 samples_rendered = audio_read_length;
570                                 need_audio = 1;
571                         }
573 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
575                         if(!video_done)
576                         {
577                                 if(audio_done)
578                                 {
579                                         video_read_length = package->video_end - video_position;
580                                         samples_rendered = Units::round((double)video_read_length /
581                                                 asset->frame_rate *
582                                                 asset->sample_rate);
583                                 }
584                                 else
585 // Guide video with audio
586                                 {
587                                         video_read_length = Units::to_int64(
588                                                 (double)(audio_position + audio_read_length) / 
589                                                 asset->sample_rate * 
590                                                 asset->frame_rate) - 
591                                                 video_position;
592                                 }
594                                 if(video_position + video_read_length >= package->video_end)
595                                 {
596                                         video_done = 1;
597                                         video_read_length = package->video_end - video_position;
598                                 }
600                                 need_video = 1;
601                         }
603 //printf("PackageRenderer::render_package 7 %d\n", result);
604                         if(need_video && !result) do_video();
605 //printf("PackageRenderer::render_package 8 %d\n", result);
606                         if(need_audio && !result) do_audio();
607 //printf("PackageRenderer::render_package 9 %d\n", result);
610                         if(!result) set_progress(samples_rendered);
612 //printf("PackageRenderer::render_package 10 %d %d %d\n", audio_read_length, video_read_length, samples_rendered);
617                         if(!result && progress_cancelled()) result = 1;
619                         if(result) 
620                                 set_result(result);
621                         else
622                                 result = get_result();
623 //printf("PackageRenderer::render_package 11 %d %d %d %d\n", audio_read_length, video_read_length, samples_rendered, result);
624                 }
626                 stop_engine();
628 //printf("PackageRenderer::render_package 12\n");
629                 stop_output();
631 //printf("PackageRenderer::render_package 13\n");
634         }
638 //printf("PackageRenderer::render_package 12\n");
639         close_output();
641 //printf("PackageRenderer::render_package 14 %d\n", result);
643         set_result(result);
645 //printf("PackageRenderer::render_package: done\n");
648         return result;
658 // Try to copy the compressed frame directly from the input to output files
659 // Return 1 on failure and 0 on success
660 int PackageRenderer::direct_frame_copy(EDL *edl, 
661         int64_t &video_position, 
662         File *file,
663         int &error)
665         Track *playable_track;
666         Edit *playable_edit;
667         int64_t frame_size;
668         int result = 0;
670 //printf("Render::direct_frame_copy 1\n");
671         if(direct_copy_possible(edl, 
672                 video_position, 
673                 playable_track, 
674                 playable_edit, 
675                 file))
676         {
677 // Switch to direct copying
678                 if(!direct_frame_copying)
679                 {
680                         if(video_write_position)
681                         {
682                                 error |= file->write_video_buffer(video_write_position);
683                                 video_write_position = 0;
684                         }
685                         file->stop_video_thread();
686                         direct_frame_copying = 1;
687                 }
688 //printf("Render::direct_frame_copy 2\n");
690                 if(!package->use_brender)
691                         error |= ((VEdit*)playable_edit)->read_frame(compressed_output, 
692                                 video_position,
693                                 PLAY_FORWARD,
694                                 video_cache);
697                 if(!error && video_preroll > 0)
698                 {
699                         video_preroll--;
700                 }
701                 else
702                 if(!error)
703                 {
704 //printf("Render::direct_frame_copy 3\n");
705 // Don't background render this one
706                         if(package->use_brender)
707                                 set_video_map(video_position, BRender::SCANNED);
709                         if(!package->use_brender)
710                         {
711                                 VFrame ***temp_output = new VFrame**[1];
712                                 temp_output[0] = new VFrame*[1];
713                                 temp_output[0][0] = compressed_output;
714                                 error |= file->write_frames(temp_output, 1);
715                                 delete temp_output[0];
716                                 delete temp_output;
717                         }
718                 }
719                 return 0;
720         }
721         else
722                 return 1;
725 int PackageRenderer::direct_copy_possible(EDL *edl,
726                                 int64_t current_position, 
727                                 Track* playable_track,  // The one track which is playable
728                                 Edit* &playable_edit, // The edit which is playing
729                                 File *file)   // Output file
731         int result = 1;
732         int total_playable_tracks = 0;
733         Track* current_track;
734         Patch* current_patch;
735         Auto* current_auto;
736         int temp;
738 // Number of playable tracks must equal 1
739         for(current_track = edl->tracks->first;
740                 current_track && result; 
741                 current_track = current_track->next)
742         {
743                 if(current_track->data_type == TRACK_VIDEO)
744                 {
745                         if(playable_tracks->is_playable(current_track, current_position))
746                         {
747                                 playable_track = current_track;
748                                 total_playable_tracks++;
749                         }
750                 }
751         }
753 //printf("Render::direct_copy_possible 1 %d\n", result);
754         if(total_playable_tracks != 1) result = 0;
755 //printf("Render::direct_copy_possible 2 %d\n", result);
757 // Edit must have a source file
758         if(result)
759         {
760 //printf("Render::direct_copy_possible 3 %d\n", result);
761                 playable_edit = playable_track->edits->get_playable_edit(current_position);
762 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
763                 if(!playable_edit)
764                         result = 0;
765         }
767 // Source file must be able to copy to destination file.
768 // Source file must be same size as project output.
769         if(result)
770         {
771 //printf("Render::direct_copy_possible 5 %d\n", result);
772                 if(!file->can_copy_from(playable_edit, 
773                         current_position,
774                         edl->session->output_w, 
775                         edl->session->output_h))
776                         result = 0;
777         }
778 //printf("Render::direct_copy_possible 6 %d\n", result);
780 // Test conditions mutual between vrender.C and this.
781         if(result && 
782                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD))
783                 result = 0;
784 //printf("Render::direct_copy_possible 7 %d\n", result);
786         return result;
799 // Get result status from server
800 int PackageRenderer::get_result()
802         return 0;
805 void PackageRenderer::set_result(int value)
809 void PackageRenderer::set_progress(int64_t value)
811 }       
813 void PackageRenderer::set_video_map(int64_t position, int value)
817 int PackageRenderer::progress_cancelled()
819         return 0;
820 }