r553: Modern gccs require __attribute__((used)) for variables used only in assembly.
[cinelerra_cv/mob.git] / cinelerra / packagerenderer.C
blob7185e9075ff7762a91e3aeea721a6435480f9abc
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(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 // 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;
370                                 result |= render_engine->vrender->process_buffer(
371                                         video_output_ptr, 
372                                         video_position, 
373                                         0);
377                                 if(mwindow && video_device->output_visible())
378                                 {
379 // Vector for video device
380                                         VFrame *preview_output[MAX_CHANNELS];
382                                         video_device->new_output_buffers(preview_output,
383                                                 command->get_edl()->session->color_model);
385                                         for(int i = 0; i < MAX_CHANNELS; i++)
386                                                 if(preview_output[i])
387                                                         preview_output[i]->copy_from(video_output_ptr[i]);
388                                         video_device->write_buffer(preview_output, 
389                                                 command->get_edl());
390                                 }
393 //printf("PackageRenderer::do_video 6\n");
395 // Write to file
396                                 if(video_preroll)
397                                 {
398 //printf("PackageRenderer::do_video 6.1\n");
399                                         video_preroll--;
400 // Keep the write position at 0 until ready to write real frames
401                                         result |= file->write_video_buffer(0);
402 //printf("PackageRenderer::do_video 6.2\n");
403                                         video_write_position = 0;
404                                 }
405                                 else
406                                 {
407 //printf("PackageRenderer::do_video 7\n");
408 // Set background rendering parameters
409 //                                      if(package->use_brender)
410 //                                      {
411 // Allow us to skip sections of the output file by setting the frame number.
412 // Used by background render and render farm.
413                                                 video_output_ptr[0]->set_number(video_position);
414 //printf("PackageRenderer::do_video 8 %p %lld\n", video_output_ptr[0], video_position);
415 //                                      }
416                                         video_write_position++;
418                                         if(video_write_position >= video_write_length)
419                                         {
420 //printf("PackageRenderer::do_video 9\n");
421                                                 result |= file->write_video_buffer(video_write_position);
422 //printf("PackageRenderer::do_video 10\n");
423 // Update the brender map after writing the files.
424                                                 if(package->use_brender)
425                                                         for(int i = 0; i < video_write_position; i++)
426                                                                 set_video_map(video_position + 1 - video_write_position + i, 
427                                                                         BRender::RENDERED);
428                                                 video_write_position = 0;
429                                         }
430 //printf("PackageRenderer::do_video 11\n");
431                                 }
434                         }
436                         video_position++;
437                         if(get_result()) result = 1;
438                         if(!result && progress_cancelled()) result = 1;
439                 }
440         }
441         else
442         {
443                 video_position += video_read_length;
444         }
445 //printf("PackageRenderer::do_video 14 %d %d\n", video_position, result);
449 void PackageRenderer::stop_engine()
451         delete render_engine;
452         delete playable_tracks;
456 void PackageRenderer::stop_output()
458         if(asset->audio_data)
459         {
460 // stop file I/O
461                 file->stop_audio_thread();
462         }
464         if(asset->video_data)
465         {
466                 delete compressed_output;
467                 if(video_write_position)
468                         file->write_video_buffer(video_write_position);
469                 if(package->use_brender)
470                         for(int i = 0; i < video_write_position; i++)
471                                 set_video_map(video_position - video_write_position + i, 
472                                         BRender::RENDERED);
473                 video_write_position = 0;       
474                 file->stop_video_thread();
475                 if(mwindow)
476                 {
477                         video_device->stop_playback();
478                         video_device->close_all();
479                         delete video_device;
480                 }
481         }
485 void PackageRenderer::close_output()
487         if(mwindow)
488                 mwindow->sighandler->pull_file(file);
489         file->close_file();
490         delete file;
491         delete asset;
494 // Aborts and returns 1 if an error is encountered.
495 int PackageRenderer::render_package(RenderPackage *package)
497         int audio_done = 0;
498         int video_done = 0;
499         int samples_rendered = 0;
502         result = 0;
503         this->package = package;
505 // printf(
506 // "PackageRenderer::render_package: audio s=%lld l=%lld video s=%lld l=%lld\n",
507 //      package->audio_start, 
508 //      package->audio_end - package->audio_start, 
509 //      package->video_start, 
510 //      package->video_end - package->video_start);
513         create_output();
515         if(!asset->video_data) video_done = 1;
516         if(!asset->audio_data) audio_done = 1;
518 // Create render engine
519         if(!result)
520         {
521                 create_engine();
523 //printf("PackageRenderer::render_package 5 %d\n", result);
525 // Main loop
526                 while((!audio_done || !video_done) && !result)
527                 {
528                         int need_audio = 0, need_video = 0;
533 // Calculate lengths to process.  Audio fragment is constant.
534                         if(!audio_done)
535                         {
536                                 if(audio_position + audio_read_length >= package->audio_end)
537                                 {
538                                         audio_done = 1;
539                                         audio_read_length = package->audio_end - audio_position;
540                                 }
542                                 samples_rendered = audio_read_length;
543                                 need_audio = 1;
544                         }
546 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
548                         if(!video_done)
549                         {
550                                 if(audio_done)
551                                 {
552                                         video_read_length = package->video_end - video_position;
553 // Packetize video length so progress gets updated
554                                         video_read_length = (int)MIN(asset->frame_rate, video_read_length);
555                                         video_read_length = MAX(video_read_length, 30);
556                                 }
557                                 else
558 // Guide video with audio
559                                 {
560                                         video_read_length = Units::to_int64(
561                                                 (double)(audio_position + audio_read_length) / 
562                                                 asset->sample_rate * 
563                                                 asset->frame_rate) - 
564                                                 video_position;
565                                 }
567 // Clamp length
568                                 if(video_position + video_read_length >= package->video_end)
569                                 {
570                                         video_done = 1;
571                                         video_read_length = package->video_end - video_position;
572                                 }
574 // Calculate samples rendered for progress bar.
575                                 if(audio_done)
576                                         samples_rendered = Units::round((double)video_read_length /
577                                                 asset->frame_rate *
578                                                 asset->sample_rate);
580                                 need_video = 1;
581                         }
583 //printf("PackageRenderer::render_package 1 %d %lld %lld\n", result, audio_read_length, video_read_length);
584                         if(need_video && !result) do_video();
585 //printf("PackageRenderer::render_package 7 %d %d\n", result, samples_rendered);
586                         if(need_audio && !result) do_audio();
589                         if(!result) set_progress(samples_rendered);
595                         if(!result && progress_cancelled()) result = 1;
597 // printf("PackageRenderer::render_package 10 %d %d %d %d\n", 
598 // audio_read_length, video_read_length, samples_rendered, result);
599                         if(result) 
600                                 set_result(result);
601                         else
602                                 result = get_result();
603                 }
605 //printf("PackageRenderer::render_package 10\n");
606                 stop_engine();
607 //printf("PackageRenderer::render_package 11\n");
609                 stop_output();
610 //printf("PackageRenderer::render_package 12\n");
613         }
617 //printf("PackageRenderer::render_package 13\n");
618         close_output();
619 //printf("PackageRenderer::render_package 14\n");
622         set_result(result);
623 //printf("PackageRenderer::render_package 15\n");
627         return result;
637 // Try to copy the compressed frame directly from the input to output files
638 // Return 1 on failure and 0 on success
639 int PackageRenderer::direct_frame_copy(EDL *edl, 
640         int64_t &video_position, 
641         File *file,
642         int &error)
644         Track *playable_track;
645         Edit *playable_edit;
646         int64_t frame_size;
647         int result = 0;
649 //printf("Render::direct_frame_copy 1\n");
650         if(direct_copy_possible(edl, 
651                 video_position, 
652                 playable_track, 
653                 playable_edit, 
654                 file))
655         {
656 // Switch to direct copying
657                 if(!direct_frame_copying)
658                 {
659                         if(video_write_position)
660                         {
661                                 error |= file->write_video_buffer(video_write_position);
662                                 video_write_position = 0;
663                         }
664                         file->stop_video_thread();
665                         direct_frame_copying = 1;
666                 }
667 //printf("Render::direct_frame_copy 2\n");
669                 if(!package->use_brender)
670                         error |= ((VEdit*)playable_edit)->read_frame(compressed_output, 
671                                 video_position,
672                                 PLAY_FORWARD,
673                                 video_cache,
674                                 1,
675                                 0);
678                 if(!error && video_preroll > 0)
679                 {
680                         video_preroll--;
681                 }
682                 else
683                 if(!error)
684                 {
685 // Don't background render this one
686                         if(package->use_brender)
687                                 set_video_map(video_position, BRender::SCANNED);
689                         if(!package->use_brender)
690                         {
691                                 VFrame ***temp_output = new VFrame**[1];
692                                 temp_output[0] = new VFrame*[1];
693                                 temp_output[0][0] = compressed_output;
694                                 error |= file->write_frames(temp_output, 1);
695                                 delete temp_output[0];
696                                 delete temp_output;
697                         }
698                 }
699                 return 0;
700         }
701         else
702                 return 1;
705 int PackageRenderer::direct_copy_possible(EDL *edl,
706                                 int64_t current_position, 
707                                 Track* playable_track,  // The one track which is playable
708                                 Edit* &playable_edit, // The edit which is playing
709                                 File *file)   // Output file
711         int result = 1;
712         int total_playable_tracks = 0;
713         Track* current_track;
714         Patch* current_patch;
715         Auto* current_auto;
716         int temp;
718 // Number of playable tracks must equal 1
719         for(current_track = edl->tracks->first;
720                 current_track && result; 
721                 current_track = current_track->next)
722         {
723                 if(current_track->data_type == TRACK_VIDEO)
724                 {
725                         if(playable_tracks->is_playable(current_track, current_position, 1))
726                         {
727                                 playable_track = current_track;
728                                 total_playable_tracks++;
729                         }
730                 }
731         }
733 //printf("Render::direct_copy_possible 1 %d\n", result);
734         if(total_playable_tracks != 1) result = 0;
735 //printf("Render::direct_copy_possible 2 %d\n", result);
737 // Edit must have a source file
738         if(result)
739         {
740 //printf("Render::direct_copy_possible 3 %d\n", result);
741                 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
742 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
743                 if(!playable_edit)
744                         result = 0;
745         }
747 // Source file must be able to copy to destination file.
748 // Source file must be same size as project output.
749         if(result)
750         {
751 //printf("Render::direct_copy_possible 5 %d\n", result);
752                 if(!file->can_copy_from(playable_edit, 
753                         current_position + playable_track->nudge,
754                         edl->session->output_w, 
755                         edl->session->output_h))
756                         result = 0;
757         }
758 //printf("Render::direct_copy_possible 6 %d\n", result);
760 // Test conditions mutual between vrender.C and this.
761         if(result && 
762                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
763                 result = 0;
764 //printf("Render::direct_copy_possible 7 %d\n", result);
766         return result;
777 int PackageRenderer::get_master()
779         return 0;
782 // Get result status from server
783 int PackageRenderer::get_result()
785         return 0;
788 void PackageRenderer::set_result(int value)
792 void PackageRenderer::set_progress(int64_t value)
794 }       
796 void PackageRenderer::set_video_map(int64_t position, int value)
800 int PackageRenderer::progress_cancelled()
802         return 0;
803 }