4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "cwindowgui.h"
34 #include "edlsession.h"
37 #include "filesystem.h"
38 #include "indexfile.h"
41 #include "mwindowgui.h"
42 #include "packagerenderer.h"
43 #include "playabletracks.h"
44 #include "playbackconfig.h"
45 #include "pluginserver.h"
46 #include "preferences.h"
48 #include "renderengine.h"
49 #include "renderfarmfsserver.h"
51 #include "sighandler.h"
53 #include "transportque.h"
56 #include "videodevice.h"
65 RenderPackage::RenderPackage()
78 RenderPackage::~RenderPackage()
89 // Used by RenderFarm and in the future, Render, to do packages.
90 PackageRenderer::PackageRenderer()
98 frames_per_second = 0;
101 PackageRenderer::~PackageRenderer()
110 // PackageRenderer::initialize happens only once for every node when doing rendering session
111 // This is not called for each package!
113 int PackageRenderer::initialize(MWindow *mwindow,
115 Preferences *preferences,
116 Asset *default_asset)
120 this->mwindow = mwindow;
122 this->preferences = preferences;
123 this->default_asset = default_asset;
126 //printf("PackageRenderer::initialize %d\n", preferences->processors);
127 command = new TransportCommand;
128 command->command = NORMAL_FWD;
129 command->get_edl()->copy_all(edl);
130 command->change_type = CHANGE_ALL;
131 command->set_playback_range(edl);
133 default_asset->frame_rate = command->get_edl()->session->frame_rate;
134 default_asset->sample_rate = command->get_edl()->session->sample_rate;
135 default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
136 command->get_edl()->session->aspect_h;
137 result = Render::check_asset(edl, *default_asset);
139 audio_cache = new CICache(preferences);
140 video_cache = new CICache(preferences);
142 //PlaybackConfig *config = command->get_edl()->session->playback_config;
143 aconfig = new AudioOutConfig();
144 vconfig = new VideoOutConfig;
149 void PackageRenderer::create_output()
152 asset = new Asset(*default_asset);
154 if(!get_master() && preferences->renderfarm_vfs && preferences->use_renderfarm)
155 sprintf(asset->path, RENDERFARM_FS_PREFIX "%s", package->path);
157 strcpy(asset->path, package->path);
161 file->set_processors(preferences->processors);
163 //printf("PackageRenderer::create_output %d\n", __LINE__);
164 result = file->open_file(preferences,
168 //printf("PackageRenderer::create_output %d %d\n", __LINE__, result);
170 if(result && mwindow)
173 char string[BCTEXTLEN];
174 sprintf(string, _("Couldn't open %s"), asset->path);
175 ErrorBox error(_(PROGRAM_NAME ": Error"),
176 mwindow->gui->get_abs_cursor_x(1),
177 mwindow->gui->get_abs_cursor_y(1));
178 error.create_objects(string);
184 mwindow->sighandler->push_file(file);
185 IndexFile::delete_index(preferences, asset);
187 //printf("PackageRenderer::create_output %d %d\n", __LINE__, result);
190 void PackageRenderer::create_engine()
192 // Fix audio buffers to 1 second
193 audio_read_length = command->get_edl()->session->sample_rate;
194 command->get_edl()->session->playback_config->aconfig->fragment_size = audio_read_length;
196 aconfig->fragment_size = audio_read_length;
199 render_engine = new RenderEngine(0, preferences, 0, 0);
200 render_engine->set_acache(audio_cache);
201 render_engine->set_vcache(video_cache);
202 render_engine->arm_command(command);
204 if(package->use_brender)
206 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
207 default_asset->frame_rate *
208 default_asset->sample_rate);
209 video_preroll = preferences->brender_preroll;
213 audio_preroll = Units::to_int64(preferences->render_preroll *
214 default_asset->sample_rate);
215 video_preroll = Units::to_int64(preferences->render_preroll *
216 default_asset->frame_rate);
218 audio_position = package->audio_start - audio_preroll;
219 if( audio_position < 0 )
221 audio_preroll += audio_position;
224 video_position = package->video_start - video_preroll;
225 if( video_position < 0 )
227 video_preroll += video_position;
234 // Create output buffers
235 if(asset->audio_data)
237 file->start_audio_thread(audio_read_length,
238 preferences->processors > 1 ? 2 : 1);
243 if(asset->video_data)
245 compressed_output = new VFrame;
246 // The write length needs to correlate with the processor count because
247 // it is passed to the file handler which usually processes frames simultaneously.
248 video_write_length = preferences->processors;
249 video_write_position = 0;
250 direct_frame_copying = 0;
253 //printf("PackageRenderer::create_engine %d\n", __LINE__);
254 file->start_video_thread(video_write_length,
255 command->get_edl()->session->color_model,
256 preferences->processors > 1 ? 2 : 1,
258 //printf("PackageRenderer::create_engine %d\n", __LINE__);
263 video_device = new VideoDevice;
264 video_device->open_output(vconfig,
265 command->get_edl()->session->frame_rate,
266 command->get_edl()->session->output_w,
267 command->get_edl()->session->output_h,
268 mwindow->cwindow->gui->canvas,
270 // video_device->start_playback();
275 playable_tracks = new PlayableTracks(render_engine->get_edl(),
286 void PackageRenderer::do_audio()
288 //printf("PackageRenderer::do_audio %d\n", __LINE__);
290 if(asset->audio_data)
292 audio_output = file->get_audio_buffer();
293 // Zero unused channels in output vector
294 for(int i = 0; i < MAX_CHANNELS; i++)
296 audio_output_ptr[i] = (i < asset->channels) ?
303 // Call render engine
305 result = render_engine->arender->process_buffer(audio_output_ptr,
311 // Fix buffers for preroll
312 int64_t output_length = audio_read_length;
313 if(audio_preroll > 0)
315 if(audio_preroll >= output_length)
319 output_length -= audio_preroll;
320 for(int i = 0; i < MAX_CHANNELS; i++)
322 if(audio_output_ptr[i])
324 double *data = audio_output_ptr[i]->get_data();
325 for(int j = 0; j < output_length; j++)
327 data[j] = data[j + audio_read_length - output_length];
332 //printf("PackageRenderer::do_audio 4\n");
334 audio_preroll -= audio_read_length;
337 // Must perform writes even if 0 length so get_audio_buffer doesn't block
338 result |= file->write_audio_buffer(output_length);
341 audio_position += audio_read_length;
342 //printf("PackageRenderer::do_audio %d\n", __LINE__);
346 void PackageRenderer::do_video()
350 if(asset->video_data)
352 // get the absolute video position from the audio position
353 int64_t video_end = video_position + video_read_length;
355 if(video_end > package->video_end)
356 video_end = package->video_end;
358 while(video_position < video_end && !result)
360 // Try to copy the compressed frame directly from the input to output files
361 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
362 if(direct_frame_copy(command->get_edl(),
367 // Direct frame copy failed.
368 // Switch back to background compression
369 if(direct_frame_copying)
372 file->start_video_thread(video_write_length,
373 command->get_edl()->session->color_model,
374 preferences->processors > 1 ? 2 : 1,
376 //printf("PackageRenderer::do_video %d %d\n", __LINE__, preferences->processors);
377 direct_frame_copying = 0;
380 // Try to use the rendering engine to write the frame.
381 // Get a buffer for background writing.
383 if(video_write_position == 0)
384 video_output = file->get_video_buffer();
386 if(debug) printf("PackageRenderer::do_video %d %p\n", __LINE__, video_output);
387 if(debug) printf("PackageRenderer::do_video %d %p\n", __LINE__, video_output[0]);
392 // Construct layered output buffer
393 video_output_ptr = video_output[0][video_write_position];
396 printf("PackageRenderer::do_video %d %p\n", __LINE__, video_output_ptr);
397 printf("PackageRenderer::do_video %d %d\n", __LINE__, result);
398 video_output_ptr->dump();
402 result = render_engine->vrender->process_buffer(
408 if(debug) printf("PackageRenderer::do_video %d %d\n", __LINE__, result);
412 video_device->output_visible())
414 // Vector for video device
415 VFrame *preview_output;
417 video_device->new_output_buffer(&preview_output,
418 command->get_edl()->session->color_model);
420 preview_output->copy_from(video_output_ptr);
421 video_device->write_buffer(preview_output,
425 if(debug) printf("PackageRenderer::do_video %d %d\n", __LINE__, result);
428 // Don't write to file
429 if(video_preroll && !result)
432 // Keep the write position at 0 until ready to write real frames
433 result = file->write_video_buffer(0);
434 video_write_position = 0;
439 // Set background rendering parameters
440 // Allow us to skip sections of the output file by setting the frame number.
441 // Used by background render and render farm.
442 //printf("PackageRenderer::do_video %d %jd\n", __LINE__, video_position);
443 video_output_ptr->set_number(video_position);
444 video_write_position++;
446 if(video_write_position >= video_write_length)
448 result = file->write_video_buffer(video_write_position);
449 //printf("PackageRenderer::do_video %d %jd\n", __LINE__, video_position);
450 // Update the brender map after writing the files.
451 if(package->use_brender)
453 //printf("PackageRenderer::do_video 10\n");
454 for(int i = 0; i < video_write_position && !result; i++)
456 result = set_video_map(video_position + 1 - video_write_position + i,
459 //printf("PackageRenderer::do_video 11 %d\n", result);
461 video_write_position = 0;
464 //printf("PackageRenderer::do_video %d %jd\n", __LINE__, video_position);
470 if(!result && get_result()) result = 1;
471 if(!result && progress_cancelled()) result = 1;
476 video_position += video_read_length;
481 void PackageRenderer::stop_engine()
483 delete render_engine;
484 delete playable_tracks;
488 void PackageRenderer::stop_output()
491 if(asset->audio_data)
494 file->stop_audio_thread();
497 if(asset->video_data)
499 delete compressed_output;
500 if(video_write_position)
501 file->write_video_buffer(video_write_position);
502 if(package->use_brender)
504 for(int i = 0; i < video_write_position && !error; i++)
506 error = set_video_map(video_position - video_write_position + i,
510 video_write_position = 0;
511 if(!error) file->stop_video_thread();
514 // video_device->stop_playback();
515 video_device->close_all();
522 void PackageRenderer::close_output()
525 mwindow->sighandler->pull_file(file);
528 asset->Garbage::remove_user();
531 // Aborts and returns 1 if an error is encountered.
532 int PackageRenderer::render_package(RenderPackage *package)
536 int samples_rendered = 0;
541 this->package = package;
544 // "PackageRenderer::render_package: audio s=%jd l=%jd video s=%jd l=%jd\n",
545 // package->audio_start,
546 // package->audio_end - package->audio_start,
547 // package->video_start,
548 // package->video_end - package->video_start);
550 if(debug) PRINT_TRACE
552 if( package->video_do ) default_asset->video_data = 1;
553 if( package->audio_do ) default_asset->audio_data = 1;
554 Render::check_asset(edl, *default_asset);
556 // FIXME: The design that we only get EDL once does not give us neccessary flexiblity to do things the way they should be donek
557 default_asset->video_data = package->video_do;
558 default_asset->audio_data = package->audio_do;
559 Render::check_asset(edl, *default_asset);
562 if(debug) PRINT_TRACE
564 if(!asset->video_data) video_done = 1;
565 if(!asset->audio_data) audio_done = 1;
567 // Create render engine
570 if(debug) PRINT_TRACE
572 if(debug) PRINT_TRACE
577 total_samples_rendered = 0;
578 while((!audio_done || !video_done) && !result)
580 int need_audio = 0, need_video = 0;
585 // Calculate lengths to process. Audio fragment is constant.
588 if(audio_position + audio_read_length >= package->audio_end)
591 audio_read_length = package->audio_end - audio_position;
594 samples_rendered = audio_read_length;
598 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
604 // video_read_length = package->video_end - video_position;
605 // // Packetize video length so progress gets updated
606 // video_read_length = (int)MIN(asset->frame_rate, video_read_length);
607 // video_read_length = MAX(video_read_length, 30);
608 video_read_length = 1;
611 // Guide video with audio
613 video_read_length = Units::to_int64(
614 (double)(audio_position + audio_read_length) /
621 if(video_position + video_read_length >= package->video_end)
624 video_read_length = package->video_end - video_position;
627 // Calculate samples rendered for progress bar.
629 samples_rendered = Units::round((double)video_read_length /
635 if(debug) PRINT_TRACE
637 if(debug) printf("PackageRenderer::render_package 1 %d %jd %jd\n",
638 result, audio_read_length, video_read_length);
639 if(need_video && !result) do_video();
640 if(debug) printf("PackageRenderer::render_package %d %d %d\n",
641 __LINE__, result, samples_rendered);
642 if(need_audio && !result) do_audio();
645 if(debug) PRINT_TRACE
648 // Calculate frames per second for the renderfarm table.
649 total_samples_rendered += samples_rendered;
650 if(!video_done && timer->get_difference() > 30000)
652 frames_per_second = (double)total_samples_rendered *
655 ((double)timer->get_difference() / 1000);
657 set_progress(samples_rendered);
659 if(debug) PRINT_TRACE
665 if(!result && progress_cancelled()) result = 1;
666 if(debug) PRINT_TRACE
668 // printf("PackageRenderer::render_package 10 %d %d %d %d\n",
669 // audio_read_length, video_read_length, samples_rendered, result);
673 result = get_result();
677 frames_per_second = (double)(package->video_end - package->video_start) /
678 ((double)timer->get_difference() / 1000);
713 // Try to copy the compressed frame directly from the input to output files
714 // Return 1 on failure and 0 on success
715 int PackageRenderer::direct_frame_copy(EDL *edl,
716 int64_t &video_position,
720 Track *playable_track = 0;
721 Edit *playable_edit = 0;
723 //printf("Render::direct_frame_copy 1\n");
724 if(direct_copy_possible(edl,
730 // Switch to direct copying
731 if(!direct_frame_copying)
733 if(video_write_position)
735 error |= file->write_video_buffer(video_write_position);
736 video_write_position = 0;
738 file->stop_video_thread();
739 direct_frame_copying = 1;
741 //printf("Render::direct_frame_copy 2\n");
743 if(!package->use_brender)
744 error |= ((VEdit*)playable_edit)->read_frame(compressed_output,
753 if(!error && video_preroll > 0)
760 if(package->use_brender)
762 //printf("PackageRenderer::direct_frame_copy 1\n");
763 error = set_video_map(video_position, BRender::SCANNED);
764 //printf("PackageRenderer::direct_frame_copy 10 %d\n", error);
768 VFrame ***temp_output = new VFrame**[1];
769 temp_output[0] = new VFrame*[1];
770 temp_output[0][0] = compressed_output;
771 error = file->write_frames(temp_output, 1);
772 delete [] temp_output[0];
773 delete [] temp_output;
782 int PackageRenderer::direct_copy_possible(EDL *edl,
783 int64_t current_position,
784 Track* &playable_track, // The one track which is playable
785 Edit* &playable_edit, // The edit which is playing
786 File *file) // Output file
789 int total_playable_tracks = 0;
790 Track* current_track;
792 // Number of playable tracks must equal 1
793 for(current_track = edl->tracks->first;
794 current_track && result;
795 current_track = current_track->next)
797 if(current_track->data_type == TRACK_VIDEO)
799 if(playable_tracks->is_playable(current_track,
804 playable_track = current_track;
805 total_playable_tracks++;
810 //printf("Render::direct_copy_possible 1 %d\n", result);
811 if(total_playable_tracks != 1) result = 0;
812 //printf("Render::direct_copy_possible 2 %d\n", result);
814 // Edit must have a source file
815 // TODO: descend into nested EDL's
818 //printf("Render::direct_copy_possible 3 %d\n", result);
819 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
820 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
825 // Source file must be able to copy to destination file.
826 // Source file must be same size as project output.
829 if(!file->can_copy_from(playable_edit->asset,
830 current_position + playable_track->nudge,
831 edl->session->output_w,
832 edl->session->output_h))
835 //printf("Render::direct_copy_possible 6 %d\n", result);
837 // Test conditions mutual between vrender.C and this.
839 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
841 //printf("Render::direct_copy_possible 7 %d\n", result);
854 int PackageRenderer::get_master()
859 // Get result status from server
860 int PackageRenderer::get_result()
865 void PackageRenderer::set_result(int value)
869 void PackageRenderer::set_progress(int64_t value)
873 int PackageRenderer::set_video_map(int64_t position, int value)
878 int PackageRenderer::progress_cancelled()