r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / renderengine.C
blobad25d07c7a1a73dc7e9c94e057ee92bde426be49
1 #include "amodule.h"
2 #include "arender.h"
3 #include "assets.h"
4 #include "audiodevice.h"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "mwindow.h"
8 #include "playbackengine.h"
9 #include "preferences.h"
10 #include "preferencesthread.h"
11 #include "renderengine.h"
12 #include "mainsession.h"
13 #include "tracks.h"
14 #include "transportque.h"
15 #include "videodevice.h"
16 #include "vrender.h"
17 #include "workarounds.h"
21 RenderEngine::RenderEngine(PlaybackEngine *playback_engine,
22         Preferences *preferences, 
23         TransportCommand *command,
24         Canvas *output,
25         ArrayList<PluginServer*> *plugindb,
26         ArrayList<Channel*> *channeldb,
27         int head_number)
28  : Thread()
30         this->playback_engine = playback_engine;
31         this->output = output;
32         this->plugindb = plugindb;
33         this->channeldb = channeldb;
34         this->head_number = head_number;
35         set_synchronous(1);
36         audio = 0;
37         video = 0;
38         arender = 0;
39         vrender = 0;
40         do_audio = 0;
41         do_video = 0;
42         interrupted = 0;
43         actual_frame_rate = 0;
44         this->preferences = new Preferences;
45         this->command = new TransportCommand;
46         *this->preferences = *preferences;
47         *this->command = *command;
48         edl = new EDL;
49         edl->create_objects();
50 // EDL only changed in construction.
51 // The EDL contained in later commands is ignored.
52         *this->edl = *command->get_edl();
53         audio_cache = 0;
54         video_cache = 0;
55         if(playback_engine && playback_engine->mwindow)
56                 mwindow = playback_engine->mwindow;
57         else
58                 mwindow = 0;
61 RenderEngine::~RenderEngine()
63 //printf("RenderEngine::~RenderEngine 1\n");
64         close_output();
65 //printf("RenderEngine::~RenderEngine 2\n");
66         delete command;
67 //printf("RenderEngine::~RenderEngine 4\n");
68         delete preferences;
69 //printf("RenderEngine::~RenderEngine 5\n");
70         if(arender) delete arender;
71 //printf("RenderEngine::~RenderEngine 6\n");
72         if(vrender) delete vrender;
73         delete edl;
74 //printf("RenderEngine::~RenderEngine 7\n");
77 int RenderEngine::arm_command(TransportCommand *command,
78         int &current_vchannel, 
79         int &current_achannel)
81 // Prevent this renderengine from accepting another command until finished.
82 // Since the renderengine is often deleted after the input_lock command it must
83 // be locked here as well as in the calling routine.
86         input_lock.lock();
89 //printf("RenderEngine::arm_command 1\n");
90         *this->command = *command;
91 //this->command->get_edl()->dump();
92 //printf("RenderEngine::arm_command 2\n");
93         int playback_strategy = command->get_edl()->session->playback_strategy;
94         this->config = command->get_edl()->session->playback_config[playback_strategy].values[head_number];
96 // Fix background rendering asset to use current dimensions and ignore
97 // headers.
98         preferences->brender_asset->frame_rate = command->get_edl()->session->frame_rate;
99         preferences->brender_asset->width = command->get_edl()->session->output_w;
100         preferences->brender_asset->height = command->get_edl()->session->output_h;
101         preferences->brender_asset->use_header = 0;
102         preferences->brender_asset->layers = 1;
103         preferences->brender_asset->video_data = 1;
105 //printf("RenderEngine::arm_command 3 %p %p\n", this->edl, command->get_edl());
106         done = 0;
107         interrupted = 0;
109 // Retool configuration for this node
110         VideoOutConfig *vconfig = this->config->vconfig;
111         AudioOutConfig *aconfig = this->config->aconfig;
112         if(command->realtime)
113         {
114                 int device_channels, edl_channels;
115                 if(command->single_frame())
116                 {
117                         vconfig->driver = PLAYBACK_X11;
118                         device_channels = 1;
119                         edl_channels = command->get_edl()->session->video_channels;
120                 }
121                 else
122                         device_channels = 1;
124                 for(int i = 0; i < MAX_CHANNELS; i++)
125                 {
126                         vconfig->do_channel[i] = 
127                                 ((i == current_vchannel) && 
128                                         device_channels &&
129                                         edl_channels);
131 // GCC 3.2 optimization error causes do_channel[0] to always be 0 unless
132 // we do this.
133 Workarounds::clamp(vconfig->do_channel[i], 0, 1);
135 //printf("RenderEngine::arm_command 1 %d\n", vconfig->do_channel[0]);
136                         if(vconfig->do_channel[i])
137                         {
138                                 current_vchannel++;
139                                 device_channels--;
140                                 edl_channels--;
141                         }
142                 }
144                 device_channels = aconfig->total_output_channels();
145                 edl_channels = command->get_edl()->session->audio_channels;
146 //printf("RenderEngine::arm_command device_channels=%d\n", device_channels);
147                 for(int i = 0; i < MAX_CHANNELS; i++)
148                 {
150                         aconfig->do_channel[i] = 
151                                 (i == current_achannel && 
152                                         device_channels &&
153                                         edl_channels);
154                         if(aconfig->do_channel[i])
155                         {
156                                 current_achannel++;
157                                 device_channels--;
158                                 edl_channels--;
159                         }
160                 }
161 // printf("RenderEngine::arm_command current_achannel=%d ", current_achannel);
162 // for(int i = 0; i < MAXCHANNELS; i++)
163 // printf("%d", aconfig->do_channel[i]);
164 // printf("\n");
166         }
167         else
168         {
169                 this->config->playback_strategy = PLAYBACK_LOCALHOST;
170                 vconfig->driver = PLAYBACK_X11;
171                 vconfig->playback_strategy = PLAYBACK_LOCALHOST;
172                 aconfig->playback_strategy = PLAYBACK_LOCALHOST;
173                 for(int i = 0; i < MAX_CHANNELS; i++)
174                 {
175                         vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
176                         vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
177                         aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
178                 }
179         }
182 //printf("RenderEngine::arm_command %p\n", vconfig);
184 //printf("RenderEngine::arm_command 4 %f %f\n", this->command->playbackstart, command->playbackstart);
185         get_duty();
187 //edl->dump();
188         if(do_audio)
189         {
190 // Larger of audio_module_fragment and fragment length adjusted for speed
191 // Extra memory must be allocated for rendering slow motion.
192                 adjusted_fragment_len = (int64_t)((float)edl->session->audio_module_fragment / 
193                         command->get_speed() + 0.5);
194                 if(adjusted_fragment_len < edl->session->audio_module_fragment)
195                         adjusted_fragment_len = edl->session->audio_module_fragment;
196         }
198 //printf("RenderEngine::arm_command 5 %d %d\n", do_audio, do_video);
199         open_output();
200 //printf("RenderEngine::arm_command 6 %d %d\n", do_audio, do_video);
201         create_render_threads();
202         arm_render_threads();
204 //printf("RenderEngine::arm_command 8\n");
205         return 0;
208 void RenderEngine::get_duty()
210         do_audio = 0;
211         do_video = 0;
213 //edl->dump();
214 //printf("RenderEngine::get_duty 1 %d %d\n", edl->tracks->playable_audio_tracks(), config->vconfig->total_playable_channels());
215         if(!command->single_frame() &&
216                 edl->tracks->playable_audio_tracks() &&
217                 config->aconfig->total_playable_channels())
218         {
219                 do_audio = 1;
220         }
222 //printf("RenderEngine::get_duty 2 %d %d\n", edl->tracks->playable_video_tracks(), config->vconfig->total_playable_channels());
223         if(edl->tracks->playable_video_tracks() &&
224                 config->vconfig->total_playable_channels())
225         {
226                 do_video = 1;
227         }
230 void RenderEngine::create_render_threads()
232         if(do_video && !vrender)
233         {
234                 vrender = new VRender(this);
235         }
237         if(do_audio && !arender)
238         {
239                 arender = new ARender(this);
240         }
244 int RenderEngine::get_output_w()
246         return edl->calculate_output_w(config->playback_strategy != PLAYBACK_LOCALHOST);
249 int RenderEngine::get_output_h()
251         return edl->calculate_output_h(config->playback_strategy != PLAYBACK_LOCALHOST);
254 int RenderEngine::brender_available(int position, int direction)
256         if(playback_engine)
257         {
258                 int64_t corrected_position = position;
259                 if(direction == PLAY_REVERSE)
260                         corrected_position--;
261                 return playback_engine->brender_available(corrected_position);
262         }
263         else
264                 return 0;
267 Channel* RenderEngine::get_current_channel()
269         if(channeldb)
270         {
271                 if(config->vconfig->buz_out_channel >= 0 && 
272                         config->vconfig->buz_out_channel < channeldb->total)
273                 {
274                         return channeldb->values[config->vconfig->buz_out_channel];
275                 }
276         }
277         return 0;
280 CICache* RenderEngine::get_acache()
282         if(playback_engine)
283                 return playback_engine->audio_cache;
284         else
285                 return audio_cache;
288 CICache* RenderEngine::get_vcache()
290         if(playback_engine)
291                 return playback_engine->video_cache;
292         else
293                 return video_cache;
296 void RenderEngine::set_acache(CICache *cache)
298         this->audio_cache = cache;
301 void RenderEngine::set_vcache(CICache *cache)
303         this->video_cache = cache;
307 double RenderEngine::get_tracking_position()
309         if(playback_engine) 
310                 return playback_engine->get_tracking_position();
311         else
312                 return 0;
315 int RenderEngine::open_output()
317 //printf("RenderEngine::open_output 1\n");
318         if(command->realtime)
319         {
320 // Allocate devices
321                 if(do_audio)
322                 {
323                         audio = new AudioDevice;
324                 }
325                 if(do_video)
326                 {
327                         video = new VideoDevice;
328                 }
330 // Initialize sharing
333 // Start playback
334                 if(do_audio && do_video)
335                 {
336                         video->set_adevice(audio);
337                         audio->set_vdevice(video);
338                 }
342 // Retool playback configuration
343                 if(do_audio)
344                 {
345                         audio->open_output(config->aconfig, 
346                                 edl->session->sample_rate, 
347                                 adjusted_fragment_len,
348                                 edl->session->real_time_playback);
349                         audio->set_software_positioning(edl->session->playback_software_position);
350                         audio->start_playback();
351                 }
353                 if(do_video)
354                 {
355                         video->open_output(config->vconfig, 
356                                 edl->session->frame_rate,
357                                 get_output_w(),
358                                 get_output_h(),
359                                 output,
360                                 command->single_frame());
361 //printf("RenderEngine::open_output 1 %d\n", config->vconfig->driver);
362                         Channel *channel = get_current_channel();
363 //printf("RenderEngine::open_output 1 %d\n", config->vconfig->driver);
364                         if(channel) video->set_channel(channel);
365 //printf("RenderEngine::open_output 1 %d\n", config->vconfig->driver);
366                         video->set_quality(80);
367 //printf("RenderEngine::open_output 1 %d\n", edl->session->smp);
368                         video->set_cpus(edl->session->smp + 1);
369 //printf("RenderEngine::open_output 2 %d\n", config->vconfig->driver);
370                 }
371         }
372 //printf("RenderEngine::open_output 2\n");
373         return 0;
376 int64_t RenderEngine::session_position()
378         if(do_audio)
379         {
380                 return audio->current_position();
381         }
383         if(do_video)
384         {
385                 return (int64_t)((double)vrender->session_frame / 
386                                 edl->session->frame_rate * 
387                                 edl->session->sample_rate /
388                                 command->get_speed() + 0.5);
389         }
392 int64_t RenderEngine::sync_position()
394         switch(edl->session->playback_strategy)
395         {
396                 case PLAYBACK_LOCALHOST:
397                 case PLAYBACK_MULTIHEAD:
398 // Use audio device
399 // No danger of race conditions because the output devices are closed after all
400 // threads join.
401 //printf("RenderEngine::sync_position 1\n");
402                         if(do_audio)
403                         {
404                                 return audio->current_position();
405                         }
407 //printf("RenderEngine::sync_position 2\n");
408                         if(do_video)
409                         {
410                                 return timer.get_scaled_difference(edl->session->sample_rate);
411                         }
412                         break;
414                 case PLAYBACK_BLONDSYMPHONY:
415                         break;
416         }
419 PluginServer* RenderEngine::scan_plugindb(char *title)
421         for(int i = 0; i < plugindb->total; i++)
422         {
423                 if(!strcasecmp(plugindb->values[i]->title, title))
424                         return plugindb->values[i];
425         }
426         return 0;
429 int RenderEngine::start_command()
431 //printf("RenderEngine::start_command 1 %d\n", command->realtime);
432         if(command->realtime)
433         {
434                 interrupt_lock.lock();
435                 start_lock.lock();
436                 Thread::start();
437                 start_lock.lock();
438                 start_lock.unlock();
439 //printf("RenderEngine::start_command 2 %p %d\n", this, Thread::get_tid());
440         }
441         return 0;
444 void RenderEngine::arm_render_threads()
446 //printf("RenderEngine::arm_render_threads 1 %d %d\n", do_audio, do_video);
447         if(do_audio)
448         {
449                 arender->arm_command();
450         }
452         if(do_video)
453         {
454 //printf("RenderEngine::arm_render_threads 1 %d %d\n", do_audio, do_video);
455                 vrender->arm_command();
456 //printf("RenderEngine::arm_render_threads 2 %d %d\n", do_audio, do_video);
457         }
461 void RenderEngine::start_render_threads()
463 // Synchronization timer
464         timer.update();
466         if(do_audio)
467         {
468                 arender->start_command();
469         }
471         if(do_video)
472         {
473                 vrender->start_command();
474         }
477 void RenderEngine::update_framerate(float framerate)
479         playback_engine->mwindow->edl->session->actual_frame_rate = framerate;
480         playback_engine->mwindow->preferences_thread->update_framerate();
483 void RenderEngine::wait_render_threads()
485         if(do_audio)
486         {
487                 arender->Thread::join();
488         }
489 //printf("RenderEngine::wait_render_threads 1\n");
490         if(do_video)
491         {
492                 vrender->Thread::join();
493         }
494 //printf("RenderEngine::wait_render_threads 2\n");
497 int RenderEngine::wait_for_completion()
499         input_lock.lock();
500         input_lock.unlock();
501         return 0;
504 void RenderEngine::interrupt_playback()
506 //printf("RenderEngine::interrupt_playback 0 %p\n", this);
507         interrupt_lock.lock();
508         interrupted = 1;
509         if(audio)
510         {
511 //printf("RenderEngine::interrupt_playback 1 %p\n", this);
512                 audio->interrupt_playback();
513 //printf("RenderEngine::interrupt_playback 2 %p\n", this);
514         }
515         if(video)
516         {
517 //printf("RenderEngine::interrupt_playback 3 %p\n", this);
518                 video->interrupt_playback();
519 //printf("RenderEngine::interrupt_playback 4 %p\n", this);
520         }
521         interrupt_lock.unlock();
524 int RenderEngine::close_output()
526 //printf("RenderEngine::close_output 1\n");
527         if(audio)
528         {
529 //printf("RenderEngine::close_output 2\n");
530                 audio->close_all();
531                 delete audio;
532                 audio = 0;
533         }
537         if(video)
538         {
539 //printf("RenderEngine::close_output 1\n");
540                 video->close_all();
541 //printf("RenderEngine::close_output 2\n");
542                 delete video;
543 //printf("RenderEngine::close_output 3\n");
544                 video = 0;
545         }
546 //printf("RenderEngine::close_output 4\n");
547         return 0;
550 void RenderEngine::get_output_levels(double *levels, int64_t position)
552         if(do_audio)
553         {
554                 int history_entry = arender->get_history_number(arender->level_samples, position);
555 //printf("RenderEngine::get_output_levels %d\n", history_entry);
556                 for(int i = 0; i < MAXCHANNELS; i++)
557                 {
558                         if(arender->audio_out[i])
559                                 levels[i] = arender->level_history[i][history_entry];
560                 }
561         }
564 void RenderEngine::get_module_levels(ArrayList<double> *module_levels, int64_t position)
566         if(do_audio)
567         {
568                 for(int i = 0; i < arender->total_modules; i++)
569                 {
570 //printf("RenderEngine::get_module_levels %p %p\n", ((AModule*)arender->modules[i]), ((AModule*)arender->modules[i])->level_samples);
571                         int history_entry = arender->get_history_number(((AModule*)arender->modules[i])->level_samples, position);
573                         module_levels->append(((AModule*)arender->modules[i])->level_history[history_entry]);
574                 }
575         }
582 void RenderEngine::run()
584 //printf("RenderEngine::run 1 %p\n", this);
585         start_render_threads();
586         start_lock.unlock();
587         interrupt_lock.unlock();
589 //printf("RenderEngine::run 2\n");
590         wait_render_threads();
591 //printf("RenderEngine::run 3\n");
593         interrupt_lock.lock();
594 //printf("RenderEngine::run 4\n");
596 //sleep(5);
597 //printf("RenderEngine::run 5\n");
599         if(interrupted)
600         {
601                 playback_engine->tracking_position = playback_engine->get_tracking_position();
602         }
603 //printf("RenderEngine::run 6\n");
605         close_output();
606 //printf("RenderEngine::run 7\n");
608 // Fix the tracking position
609         if(playback_engine)
610         {
611                 if(command->command == CURRENT_FRAME)
612                 {
613 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
614                         playback_engine->tracking_position = command->playbackstart;
615                 }
616                 else
617                 {
618 // Make sure transport doesn't issue a pause command next
619 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
620                         if(!interrupted)
621                         {
622                                 if(do_audio)
623                                         playback_engine->tracking_position = 
624                                                 (double)arender->current_position / 
625                                                         command->get_edl()->session->sample_rate;
626                                 else
627                                 if(do_video)
628                                 {
629                                         playback_engine->tracking_position = 
630                                                 (double)vrender->current_position / 
631                                                         command->get_edl()->session->frame_rate;
632                                 }
633                         }
635                         if(!interrupted) playback_engine->command->command = STOP;
636 //printf("RenderEngine::run 8\n");
637                         playback_engine->stop_tracking();
639 //printf("RenderEngine::run 9\n");
640                 }
641                 playback_engine->is_playing_back = 0;
642         }
644 //printf("RenderEngine::run 10\n");
645         input_lock.unlock();
646 //printf("RenderEngine::run 6\n");
647         interrupt_lock.unlock();
648 //printf("RenderEngine::run 7 %p\n", this);
675 int RenderEngine::reset_parameters()
677         start_position = 0;
678         follow_loop = 0;
679         end_position = 0;
680         infinite = 0;
681         reverse = 0;
682         start_position = 0;
683         audio_channels = 0;
684         do_audio = 0;
685         do_video = 0;
686         done = 0;
689 int RenderEngine::arm_playback_common(int64_t start_sample, 
690                         int64_t end_sample,
691                         int64_t current_sample,
692                         int reverse, 
693                         float speed, 
694                         int follow_loop,
695                         int infinite)
697         this->follow_loop = follow_loop;
698         this->start_position = start_sample;
699         this->end_position = end_sample;
700         this->reverse = reverse;
701         this->infinite = infinite;
702         this->current_sample = current_sample;
703         if(infinite) this->follow_loop = 0;
706 int RenderEngine::arm_playback_audio(int64_t input_length, 
707                         int64_t amodule_render_fragment, 
708                         int64_t playback_buffer, 
709                         int64_t output_length, 
710                         int audio_channels)
712         this->audio_channels = audio_channels;
714         do_audio = 1;
716         arender = new ARender(this);
717         arender->arm_playback(current_sample, 
718                                                         input_length, 
719                                                         amodule_render_fragment, 
720                                                         playback_buffer, 
721                                                         output_length);
724 int RenderEngine::arm_playback_video(int every_frame, 
725                         int64_t read_length, 
726                         int64_t output_length,
727                         int track_w,
728                         int track_h,
729                         int output_w,
730                         int output_h)
732         do_video = 1;
733         this->every_frame = every_frame;
735         vrender = new VRender(this);
736 //      vrender->arm_playback(current_sample, 
737 //                                                      read_length, 
738 //                                                      output_length, 
739 //                                                      output_length, 
740 //                                                      track_w,
741 //                                                      track_h,
742 //                                                      output_w,
743 //                                                      output_h);
746 int RenderEngine::start_video()
748 // start video for realtime
749         if(video) video->start_playback();
750         vrender->start_playback();
754 int64_t RenderEngine::get_correction_factor(int reset)
756         if(!every_frame)
757         {
758                 int64_t x;
759 //              x = playbackengine->correction_factor;
760 //              if(reset) playbackengine->correction_factor = 0;
761                 return x;
762         }
763         else
764                 return 0;
767 int RenderEngine::wait_for_startup()
769         if(do_audio) arender->wait_for_startup();
770         if(do_video) vrender->wait_for_startup();