r1014: Enable horizontal scrolling with the mouse wheel by pressing Ctrl.
[cinelerra_cv/ct.git] / cinelerra / packagerenderer.C
blobd7d1eb3ccd8239b1ae3c506e922bc9433bc0c154
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;
80         delete aconfig;
83 // PackageRenderer::initialize happens only once for every node when doing rendering session
84 // This is not called for each package!
86 int PackageRenderer::initialize(MWindow *mwindow,
87                 EDL *edl, 
88                 Preferences *preferences, 
89                 Asset *default_asset,
90                 ArrayList<PluginServer*> *plugindb)
92         int result = 0;
94         this->mwindow = mwindow;
95         this->edl = edl;
96         this->preferences = preferences;
97         this->default_asset = default_asset;
98         this->plugindb = plugindb;
101 //printf("PackageRenderer::initialize %d\n", preferences->processors);
102         command = new TransportCommand;
103         command->command = NORMAL_FWD;
104         command->get_edl()->copy_all(edl);
105         command->change_type = CHANGE_ALL;
106         command->set_playback_range(edl);
108         default_asset->frame_rate = command->get_edl()->session->frame_rate;
109         default_asset->sample_rate = command->get_edl()->session->sample_rate;
110         default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
111                 command->get_edl()->session->aspect_h;
112         result = Render::check_asset(edl, *default_asset);
114         audio_cache = new CICache(preferences, plugindb);
115         video_cache = new CICache(preferences, plugindb);
117         PlaybackConfig *config = command->get_edl()->session->playback_config;
118         aconfig = new AudioOutConfig(0);
119         vconfig = new VideoOutConfig;
121         return result;
124 void PackageRenderer::create_output()
126         FileSystem fs;
127         asset = new Asset(*default_asset);
133         strcpy(asset->path, package->path);
136         
138         file = new File;
140         file->set_processors(preferences->processors);
142         result = file->open_file(preferences, 
143                                         asset, 
144                                         0, 
145                                         1, 
146                                         command->get_edl()->session->sample_rate, 
147                                         command->get_edl()->session->frame_rate);
148 //printf("PackageRenderer::create_output 10 %d\n", result);
150         if(result && mwindow)
151         {
152 // open failed
153                 char string[BCTEXTLEN];
154                 sprintf(string, _("Couldn't open %s"), asset->path);
155                 ErrorBox error(PROGRAM_NAME ": Error",
156                         mwindow->gui->get_abs_cursor_x(1),
157                         mwindow->gui->get_abs_cursor_y(1));
158                 error.create_objects(string);
159                 error.run_window();
160         }
161         else
162         if(mwindow)
163         {
164                 mwindow->sighandler->push_file(file);
165                 IndexFile::delete_index(preferences, asset);
166         }
167 //printf("PackageRenderer::create_output 100 %d\n", result);
170 void PackageRenderer::create_engine()
172         int current_achannel = 0, current_vchannel = 0;
173         audio_read_length = command->get_edl()->session->sample_rate;
175         aconfig->fragment_size = audio_read_length;
178         render_engine = new RenderEngine(0,
179                 preferences,
180                 command,
181                 0,
182                 plugindb,
183                 0);
184         render_engine->set_acache(audio_cache);
185         render_engine->set_vcache(video_cache);
186         render_engine->arm_command(command, current_achannel, current_vchannel);
188         if(package->use_brender)
189         {
190                 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
191                         default_asset->frame_rate *
192                         default_asset->sample_rate);
193                 video_preroll = preferences->brender_preroll;
194         }
195         else
196         {
197                 audio_preroll = Units::to_int64(preferences->render_preroll * 
198                         default_asset->sample_rate);
199                 video_preroll = Units::to_int64(preferences->render_preroll * 
200                         default_asset->frame_rate);
201         }
202         audio_position = package->audio_start - audio_preroll;
203         video_position = package->video_start - video_preroll;
208 // Create output buffers
209         if(asset->audio_data)
210         {
211                 file->start_audio_thread(audio_read_length, 
212                         preferences->processors > 1 ? 2 : 1);
213         }
216         if(asset->video_data)
217         {
218                 compressed_output = new VFrame;
219 // The write length needs to correlate with the processor count because
220 // it is passed to the file handler which usually processes frames simultaneously.
221                 video_write_length = preferences->processors;
222                 video_write_position = 0;
223                 direct_frame_copying = 0;
226 //printf("PackageRenderer::create_engine 1\n");
227                 file->start_video_thread(video_write_length,
228                         command->get_edl()->session->color_model,
229                         preferences->processors > 1 ? 2 : 1,
230                         0);
233                 if(mwindow)
234                 {
235                         video_device = new VideoDevice;
236                         video_device->open_output(vconfig, 
237                                 command->get_edl()->session->frame_rate, 
238                                 command->get_edl()->session->output_w, 
239                                 command->get_edl()->session->output_h, 
240                                 mwindow->cwindow->gui->canvas,
241                                 0);
242                         video_device->start_playback();
243                 }
244         }
247         playable_tracks = new PlayableTracks(render_engine, 
248                 video_position, 
249                 TRACK_VIDEO,
250                 1);
257 void PackageRenderer::do_audio()
259 //printf("PackageRenderer::do_audio 1\n");
260 // Do audio data
261         if(asset->audio_data)
262         {
263                 audio_output = file->get_audio_buffer();
264 // Zero unused channels in output vector
265                 for(int i = 0; i < MAX_CHANNELS; i++)
266                         audio_output_ptr[i] = (i < asset->channels) ? 
267                                 audio_output[i] : 
268                                 0;
273 // Call render engine
274                 result = render_engine->arender->process_buffer(audio_output_ptr, 
275                         audio_read_length, 
276                         audio_position,
277                         0);
279 //printf("PackageRenderer::do_audio 3\n");
282 // Fix buffers for preroll
283                 int64_t output_length = audio_read_length;
284                 if(audio_preroll > 0)
285                 {
286                         if(audio_preroll >= output_length)
287                                 output_length = 0;
288                         else
289                         {
290                                 output_length -= audio_preroll;
291                                 for(int i = 0; i < MAX_CHANNELS; i++)
292                                 {
293                                         if(audio_output_ptr[i])
294                                                 for(int j = 0; j < output_length; j++)
295                                                 {
296                                                         audio_output_ptr[i][j] = audio_output_ptr[i][j + audio_read_length - output_length];
297                                                 }
298                                 }
299                         }
300 //printf("PackageRenderer::do_audio 4\n");
302                         audio_preroll -= audio_read_length;
303                 }
305 // Must perform writes even if 0 length so get_audio_buffer doesn't block
306                 result |= file->write_audio_buffer(output_length);
307         }
309         audio_position += audio_read_length;
310 //printf("PackageRenderer::do_audio 5\n");
314 void PackageRenderer::do_video()
316 // Do video data
317         if(asset->video_data)
318         {
319 // get the absolute video position from the audio position
320                 int64_t video_end = video_position + video_read_length;
322                 if(video_end > package->video_end)
323                         video_end = package->video_end;
325                 while(video_position < video_end && !result)
326                 {
327 // Try to copy the compressed frame directly from the input to output files
328 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
329                         if(direct_frame_copy(command->get_edl(), 
330                                 video_position, 
331                                 file, 
332                                 result))
333                         {
334 // Direct frame copy failed.
335 // Switch back to background compression
336                                 if(direct_frame_copying)
337                                 {
338                                         file->start_video_thread(video_write_length, 
339                                                 command->get_edl()->session->color_model,
340                                                 preferences->processors > 1 ? 2 : 1,
341                                                 0);
342                                         direct_frame_copying = 0;
343                                 }
345 // Try to use the rendering engine to write the frame.
346 // Get a buffer for background writing.
350                                 if(video_write_position == 0)
351                                         video_output = file->get_video_buffer();
357 // Construct layered output buffer
358                                 video_output_ptr = video_output[0][video_write_position];
360                                 if(!result)
361                                         result = render_engine->vrender->process_buffer(
362                                                 video_output_ptr, 
363                                                 video_position, 
364                                                 0);
368                                 if(!result && 
369                                         mwindow && 
370                                         video_device->output_visible())
371                                 {
372 // Vector for video device
373                                         VFrame *preview_output;
375                                         video_device->new_output_buffer(&preview_output,
376                                                 command->get_edl()->session->color_model);
378                                         preview_output->copy_from(video_output_ptr);
379                                         video_device->write_buffer(preview_output, 
380                                                 command->get_edl());
381                                 }
385 // Don't write to file
386                                 if(video_preroll && !result)
387                                 {
388                                         video_preroll--;
389 // Keep the write position at 0 until ready to write real frames
390                                         result = file->write_video_buffer(0);
391                                         video_write_position = 0;
392                                 }
393                                 else
394                                 if(!result)
395                                 {
396 // Set background rendering parameters
397 // Allow us to skip sections of the output file by setting the frame number.
398 // Used by background render and render farm.
399                                         video_output_ptr->set_number(video_position);
400                                         video_write_position++;
402                                         if(video_write_position >= video_write_length)
403                                         {
404 //printf("PackageRenderer::do_video 9\n");
405                                                 result = file->write_video_buffer(video_write_position);
406 // Update the brender map after writing the files.
407                                                 if(package->use_brender)
408                                                 {
409 //printf("PackageRenderer::do_video 10\n");
410                                                         for(int i = 0; i < video_write_position && !result; i++)
411                                                         {
412                                                                 result = set_video_map(video_position + 1 - video_write_position + i, 
413                                                                         BRender::RENDERED);
414                                                         }
415 //printf("PackageRenderer::do_video 11 %d\n", result);
416                                                 }
417                                                 video_write_position = 0;
418                                         }
419                                 }
422                         }
424                         video_position++;
425                         if(!result && get_result()) result = 1;
426                         if(!result && progress_cancelled()) result = 1;
427                 }
428         }
429         else
430         {
431                 video_position += video_read_length;
432         }
436 void PackageRenderer::stop_engine()
438         delete render_engine;
439         delete playable_tracks;
443 void PackageRenderer::stop_output()
445         int error = 0;
446         if(asset->audio_data)
447         {
448 // stop file I/O
449                 file->stop_audio_thread();
450         }
452         if(asset->video_data)
453         {
454                 delete compressed_output;
455                 if(video_write_position)
456                         file->write_video_buffer(video_write_position);
457                 if(package->use_brender)
458                 {
459                         for(int i = 0; i < video_write_position && !error; i++)
460                         {
461                                 error = set_video_map(video_position - video_write_position + i, 
462                                         BRender::RENDERED);
463                         }
464                 }
465                 video_write_position = 0;       
466                 if(!error) file->stop_video_thread();
467                 if(mwindow)
468                 {
469                         video_device->stop_playback();
470                         video_device->close_all();
471                         delete video_device;
472                 }
473         }
477 void PackageRenderer::close_output()
479         if(mwindow)
480                 mwindow->sighandler->pull_file(file);
481         file->close_file();
482         delete file;
483         Garbage::delete_object(asset);
486 // Aborts and returns 1 if an error is encountered.
487 int PackageRenderer::render_package(RenderPackage *package)
489         int audio_done = 0;
490         int video_done = 0;
491         int samples_rendered = 0;
494         result = 0;
495         this->package = package;
497 // printf(
498 // "PackageRenderer::render_package: audio s=%lld l=%lld video s=%lld l=%lld\n",
499 //      package->audio_start, 
500 //      package->audio_end - package->audio_start, 
501 //      package->video_start, 
502 //      package->video_end - package->video_start);
505 // FIXME: The design that we only get EDL once does not give us neccessary flexiblity to do things the way they should be donek
506         default_asset->video_data = package->video_do;
507         default_asset->audio_data = package->audio_do;
508         Render::check_asset(edl, *default_asset);
509         
510         create_output();
512         if(!asset->video_data) video_done = 1;
513         if(!asset->audio_data) audio_done = 1;
515 // Create render engine
516         if(!result)
517         {
518                 create_engine();
520 //printf("PackageRenderer::render_package 5 %d\n", result);
522 // Main loop
523                 while((!audio_done || !video_done) && !result)
524                 {
525                         int need_audio = 0, need_video = 0;
530 // Calculate lengths to process.  Audio fragment is constant.
531                         if(!audio_done)
532                         {
533                                 if(audio_position + audio_read_length >= package->audio_end)
534                                 {
535                                         audio_done = 1;
536                                         audio_read_length = package->audio_end - audio_position;
537                                 }
539                                 samples_rendered = audio_read_length;
540                                 need_audio = 1;
541                         }
543 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
545                         if(!video_done)
546                         {
547                                 if(audio_done)
548                                 {
549                                         video_read_length = package->video_end - video_position;
550 // Packetize video length so progress gets updated
551                                         video_read_length = (int)MIN(asset->frame_rate, video_read_length);
552                                         video_read_length = MAX(video_read_length, 30);
553                                 }
554                                 else
555 // Guide video with audio
556                                 {
557                                         video_read_length = Units::to_int64(
558                                                 (double)(audio_position + audio_read_length) / 
559                                                 asset->sample_rate * 
560                                                 asset->frame_rate) - 
561                                                 video_position;
562                                 }
564 // Clamp length
565                                 if(video_position + video_read_length >= package->video_end)
566                                 {
567                                         video_done = 1;
568                                         video_read_length = package->video_end - video_position;
569                                 }
571 // Calculate samples rendered for progress bar.
572                                 if(audio_done)
573                                         samples_rendered = Units::round((double)video_read_length /
574                                                 asset->frame_rate *
575                                                 asset->sample_rate);
577                                 need_video = 1;
578                         }
580 //printf("PackageRenderer::render_package 1 %d %lld %lld\n", result, audio_read_length, video_read_length);
581                         if(need_video && !result) do_video();
582 //printf("PackageRenderer::render_package 7 %d %d\n", result, samples_rendered);
583                         if(need_audio && !result) do_audio();
586                         if(!result) set_progress(samples_rendered);
592                         if(!result && progress_cancelled()) result = 1;
594 // printf("PackageRenderer::render_package 10 %d %d %d %d\n", 
595 // audio_read_length, video_read_length, samples_rendered, result);
596                         if(result) 
597                                 set_result(result);
598                         else
599                                 result = get_result();
600                 }
602 //printf("PackageRenderer::render_package 20\n");
603                 stop_engine();
604 //printf("PackageRenderer::render_package 30\n");
606                 stop_output();
607 //printf("PackageRenderer::render_package 40\n");
610         }
614 //printf("PackageRenderer::render_package 50\n");
615         close_output();
616 //printf("PackageRenderer::render_package 60\n");
619         set_result(result);
620 //printf("PackageRenderer::render_package 70\n");
624         return result;
634 // Try to copy the compressed frame directly from the input to output files
635 // Return 1 on failure and 0 on success
636 int PackageRenderer::direct_frame_copy(EDL *edl, 
637         int64_t &video_position, 
638         File *file,
639         int &error)
641         Track *playable_track;
642         Edit *playable_edit;
643         int64_t frame_size;
645 //printf("Render::direct_frame_copy 1\n");
646         if(direct_copy_possible(edl, 
647                 video_position, 
648                 playable_track, 
649                 playable_edit, 
650                 file))
651         {
652 // Switch to direct copying
653                 if(!direct_frame_copying)
654                 {
655                         if(video_write_position)
656                         {
657                                 error |= file->write_video_buffer(video_write_position);
658                                 video_write_position = 0;
659                         }
660                         file->stop_video_thread();
661                         direct_frame_copying = 1;
662                 }
663 //printf("Render::direct_frame_copy 2\n");
665                 if(!package->use_brender)
666                         error |= ((VEdit*)playable_edit)->read_frame(compressed_output, 
667                                 video_position,
668                                 PLAY_FORWARD,
669                                 video_cache,
670                                 1,
671                                 0,
672                                 0);
675                 if(!error && video_preroll > 0)
676                 {
677                         video_preroll--;
678                 }
679                 else
680                 if(!error)
681                 {
682                         if(package->use_brender)
683                         {
684 //printf("PackageRenderer::direct_frame_copy 1\n");
685                                 error = set_video_map(video_position, BRender::SCANNED);
686 //printf("PackageRenderer::direct_frame_copy 10 %d\n", error);
687                         }
688                         else
689                         {
690                                 VFrame ***temp_output = new VFrame**[1];
691                                 temp_output[0] = new VFrame*[1];
692                                 temp_output[0][0] = compressed_output;
693                                 error = file->write_frames(temp_output, 1);
694                                 delete [] temp_output[0];
695                                 delete temp_output;
696                         }
697                 }
698                 return 0;
699         }
700         else
701                 return 1;
704 int PackageRenderer::direct_copy_possible(EDL *edl,
705                                 int64_t current_position, 
706                                 Track* playable_track,  // The one track which is playable
707                                 Edit* &playable_edit, // The edit which is playing
708                                 File *file)   // Output file
710         int result = 1;
711         int total_playable_tracks = 0;
712         Track* current_track;
713         Patch* current_patch;
714         Auto* current_auto;
715         int temp;
717 // Number of playable tracks must equal 1
718         for(current_track = edl->tracks->first;
719                 current_track && result; 
720                 current_track = current_track->next)
721         {
722                 if(current_track->data_type == TRACK_VIDEO)
723                 {
724                         if(playable_tracks->is_playable(current_track, current_position, 1))
725                         {
726                                 playable_track = current_track;
727                                 total_playable_tracks++;
728                         }
729                 }
730         }
732 //printf("Render::direct_copy_possible 1 %d\n", result);
733         if(total_playable_tracks != 1) result = 0;
734 //printf("Render::direct_copy_possible 2 %d\n", result);
736 // Edit must have a source file
737         if(result)
738         {
739 //printf("Render::direct_copy_possible 3 %d\n", result);
740                 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
741 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
742                 if(!playable_edit)
743                         result = 0;
744         }
746 // Source file must be able to copy to destination file.
747 // Source file must be same size as project output.
748         if(result)
749         {
750 //printf("Render::direct_copy_possible 5 %d\n", result);
751                 if(!file->can_copy_from(playable_edit, 
752                         current_position + playable_track->nudge,
753                         edl->session->output_w, 
754                         edl->session->output_h))
755                         result = 0;
756         }
757 //printf("Render::direct_copy_possible 6 %d\n", result);
759 // Test conditions mutual between vrender.C and this.
760         if(result && 
761                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
762                 result = 0;
763 //printf("Render::direct_copy_possible 7 %d\n", result);
765         return result;
776 int PackageRenderer::get_master()
778         return 0;
781 // Get result status from server
782 int PackageRenderer::get_result()
784         return 0;
787 void PackageRenderer::set_result(int value)
791 void PackageRenderer::set_progress(int64_t value)
793 }       
795 int PackageRenderer::set_video_map(int64_t position, int value)
799 int PackageRenderer::progress_cancelled()
801         return 0;
802 }