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
29
#include "cwindowgui.h"
33
#include "edlsession.h"
36
#include "filesystem.h"
37
#include "indexfile.h"
40
#include "mwindowgui.h"
41
#include "packagerenderer.h"
42
#include "playabletracks.h"
43
#include "playbackconfig.h"
44
#include "pluginserver.h"
45
#include "preferences.h"
47
#include "renderengine.h"
48
#include "renderfarmfsserver.h"
49
#include "sighandler.h"
51
#include "transportque.h"
54
#include "videodevice.h"
63
RenderPackage::RenderPackage()
74
RenderPackage::~RenderPackage()
85
// Used by RenderFarm and in the future, Render, to do packages.
86
PackageRenderer::PackageRenderer()
95
PackageRenderer::~PackageRenderer()
104
// PackageRenderer::initialize happens only once for every node when doing rendering session
105
// This is not called for each package!
107
int PackageRenderer::initialize(MWindow *mwindow,
109
Preferences *preferences,
110
Asset *default_asset,
111
ArrayList<PluginServer*> *plugindb)
115
this->mwindow = mwindow;
117
this->preferences = preferences;
118
this->default_asset = default_asset;
119
this->plugindb = plugindb;
122
//printf("PackageRenderer::initialize %d\n", preferences->processors);
123
command = new TransportCommand;
124
command->command = NORMAL_FWD;
125
command->get_edl()->copy_all(edl);
126
command->change_type = CHANGE_ALL;
127
command->set_playback_range(edl);
129
default_asset->frame_rate = command->get_edl()->session->frame_rate;
130
default_asset->sample_rate = command->get_edl()->session->sample_rate;
131
default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
132
command->get_edl()->session->aspect_h;
133
result = Render::check_asset(edl, *default_asset);
135
audio_cache = new CICache(preferences, plugindb);
136
video_cache = new CICache(preferences, plugindb);
138
PlaybackConfig *config = command->get_edl()->session->playback_config;
139
aconfig = new AudioOutConfig(0);
140
vconfig = new VideoOutConfig;
145
void PackageRenderer::create_output()
148
asset = new Asset(*default_asset);
154
strcpy(asset->path, package->path);
161
file->set_processors(preferences->processors);
163
result = file->open_file(preferences,
167
command->get_edl()->session->sample_rate,
168
command->get_edl()->session->frame_rate);
169
//printf("PackageRenderer::create_output 10 %d\n", result);
171
if(result && mwindow)
174
char string[BCTEXTLEN];
175
sprintf(string, _("Couldn't open %s"), asset->path);
176
ErrorBox error(PROGRAM_NAME ": Error",
177
mwindow->gui->get_abs_cursor_x(1),
178
mwindow->gui->get_abs_cursor_y(1));
179
error.create_objects(string);
185
mwindow->sighandler->push_file(file);
186
IndexFile::delete_index(preferences, asset);
188
//printf("PackageRenderer::create_output 100 %d\n", result);
191
void PackageRenderer::create_engine()
193
int current_achannel = 0, current_vchannel = 0;
194
audio_read_length = command->get_edl()->session->sample_rate;
196
aconfig->fragment_size = audio_read_length;
199
render_engine = new RenderEngine(0,
205
render_engine->set_acache(audio_cache);
206
render_engine->set_vcache(video_cache);
207
render_engine->arm_command(command, current_achannel, current_vchannel);
209
if(package->use_brender)
211
audio_preroll = Units::to_int64((double)preferences->brender_preroll /
212
default_asset->frame_rate *
213
default_asset->sample_rate);
214
video_preroll = preferences->brender_preroll;
218
audio_preroll = Units::to_int64(preferences->render_preroll *
219
default_asset->sample_rate);
220
video_preroll = Units::to_int64(preferences->render_preroll *
221
default_asset->frame_rate);
223
audio_position = package->audio_start - audio_preroll;
224
video_position = package->video_start - video_preroll;
229
// Create output buffers
230
if(asset->audio_data)
232
file->start_audio_thread(audio_read_length,
233
preferences->processors > 1 ? 2 : 1);
237
if(asset->video_data)
239
compressed_output = new VFrame;
240
// The write length needs to correlate with the processor count because
241
// it is passed to the file handler which usually processes frames simultaneously.
242
video_write_length = preferences->processors;
243
video_write_position = 0;
244
direct_frame_copying = 0;
247
//printf("PackageRenderer::create_engine 1\n");
248
file->start_video_thread(video_write_length,
249
command->get_edl()->session->color_model,
250
preferences->processors > 1 ? 2 : 1,
256
video_device = new VideoDevice;
257
video_device->open_output(vconfig,
258
command->get_edl()->session->frame_rate,
259
command->get_edl()->session->output_w,
260
command->get_edl()->session->output_h,
261
mwindow->cwindow->gui->canvas,
263
video_device->start_playback();
268
playable_tracks = new PlayableTracks(render_engine,
278
void PackageRenderer::do_audio()
280
//printf("PackageRenderer::do_audio 1\n");
282
if(asset->audio_data)
284
audio_output = file->get_audio_buffer();
285
// Zero unused channels in output vector
286
for(int i = 0; i < MAX_CHANNELS; i++)
287
audio_output_ptr[i] = (i < asset->channels) ?
294
// Call render engine
295
result = render_engine->arender->process_buffer(audio_output_ptr,
300
//printf("PackageRenderer::do_audio 3\n");
303
// Fix buffers for preroll
304
int64_t output_length = audio_read_length;
305
if(audio_preroll > 0)
307
if(audio_preroll >= output_length)
311
output_length -= audio_preroll;
312
for(int i = 0; i < MAX_CHANNELS; i++)
314
if(audio_output_ptr[i])
315
for(int j = 0; j < output_length; j++)
317
audio_output_ptr[i][j] = audio_output_ptr[i][j + audio_read_length - output_length];
321
//printf("PackageRenderer::do_audio 4\n");
323
audio_preroll -= audio_read_length;
326
// Must perform writes even if 0 length so get_audio_buffer doesn't block
327
result |= file->write_audio_buffer(output_length);
330
audio_position += audio_read_length;
331
//printf("PackageRenderer::do_audio 5\n");
335
void PackageRenderer::do_video()
338
if(asset->video_data)
340
// get the absolute video position from the audio position
341
int64_t video_end = video_position + video_read_length;
343
if(video_end > package->video_end)
344
video_end = package->video_end;
346
while(video_position < video_end && !result)
348
// Try to copy the compressed frame directly from the input to output files
349
//printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
350
if(direct_frame_copy(command->get_edl(),
355
// Direct frame copy failed.
356
// Switch back to background compression
357
if(direct_frame_copying)
359
file->start_video_thread(video_write_length,
360
command->get_edl()->session->color_model,
361
preferences->processors > 1 ? 2 : 1,
363
direct_frame_copying = 0;
366
// Try to use the rendering engine to write the frame.
367
// Get a buffer for background writing.
371
if(video_write_position == 0)
372
video_output = file->get_video_buffer();
378
// Construct layered output buffer
379
video_output_ptr = video_output[0][video_write_position];
382
result = render_engine->vrender->process_buffer(
391
video_device->output_visible())
393
// Vector for video device
394
VFrame *preview_output;
396
video_device->new_output_buffer(&preview_output,
397
command->get_edl()->session->color_model);
399
preview_output->copy_from(video_output_ptr);
400
video_device->write_buffer(preview_output,
406
// Don't write to file
407
if(video_preroll && !result)
410
// Keep the write position at 0 until ready to write real frames
411
result = file->write_video_buffer(0);
412
video_write_position = 0;
417
// Set background rendering parameters
418
// Allow us to skip sections of the output file by setting the frame number.
419
// Used by background render and render farm.
420
video_output_ptr->set_number(video_position);
421
video_write_position++;
423
if(video_write_position >= video_write_length)
425
//printf("PackageRenderer::do_video 9\n");
426
result = file->write_video_buffer(video_write_position);
427
// Update the brender map after writing the files.
428
if(package->use_brender)
430
//printf("PackageRenderer::do_video 10\n");
431
for(int i = 0; i < video_write_position && !result; i++)
433
result = set_video_map(video_position + 1 - video_write_position + i,
436
//printf("PackageRenderer::do_video 11 %d\n", result);
438
video_write_position = 0;
446
if(!result && get_result()) result = 1;
447
if(!result && progress_cancelled()) result = 1;
452
video_position += video_read_length;
457
void PackageRenderer::stop_engine()
459
delete render_engine;
460
delete playable_tracks;
464
void PackageRenderer::stop_output()
467
if(asset->audio_data)
470
file->stop_audio_thread();
473
if(asset->video_data)
475
delete compressed_output;
476
if(video_write_position)
477
file->write_video_buffer(video_write_position);
478
if(package->use_brender)
480
for(int i = 0; i < video_write_position && !error; i++)
482
error = set_video_map(video_position - video_write_position + i,
486
video_write_position = 0;
487
if(!error) file->stop_video_thread();
490
video_device->stop_playback();
491
video_device->close_all();
498
void PackageRenderer::close_output()
501
mwindow->sighandler->pull_file(file);
504
Garbage::delete_object(asset);
507
// Aborts and returns 1 if an error is encountered.
508
int PackageRenderer::render_package(RenderPackage *package)
512
int samples_rendered = 0;
516
this->package = package;
519
// "PackageRenderer::render_package: audio s=%lld l=%lld video s=%lld l=%lld\n",
520
// package->audio_start,
521
// package->audio_end - package->audio_start,
522
// package->video_start,
523
// package->video_end - package->video_start);
526
// FIXME: The design that we only get EDL once does not give us neccessary flexiblity to do things the way they should be donek
527
default_asset->video_data = package->video_do;
528
default_asset->audio_data = package->audio_do;
529
Render::check_asset(edl, *default_asset);
533
if(!asset->video_data) video_done = 1;
534
if(!asset->audio_data) audio_done = 1;
536
// Create render engine
541
//printf("PackageRenderer::render_package 5 %d\n", result);
544
while((!audio_done || !video_done) && !result)
546
int need_audio = 0, need_video = 0;
551
// Calculate lengths to process. Audio fragment is constant.
554
if(audio_position + audio_read_length >= package->audio_end)
557
audio_read_length = package->audio_end - audio_position;
560
samples_rendered = audio_read_length;
564
//printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
570
video_read_length = package->video_end - video_position;
571
// Packetize video length so progress gets updated
572
video_read_length = (int)MIN(asset->frame_rate, video_read_length);
573
video_read_length = MAX(video_read_length, 30);
576
// Guide video with audio
578
video_read_length = Units::to_int64(
579
(double)(audio_position + audio_read_length) /
586
if(video_position + video_read_length >= package->video_end)
589
video_read_length = package->video_end - video_position;
592
// Calculate samples rendered for progress bar.
594
samples_rendered = Units::round((double)video_read_length /
601
//printf("PackageRenderer::render_package 1 %d %lld %lld\n", result, audio_read_length, video_read_length);
602
if(need_video && !result) do_video();
603
//printf("PackageRenderer::render_package 7 %d %d\n", result, samples_rendered);
604
if(need_audio && !result) do_audio();
607
if(!result) set_progress(samples_rendered);
613
if(!result && progress_cancelled()) result = 1;
615
// printf("PackageRenderer::render_package 10 %d %d %d %d\n",
616
// audio_read_length, video_read_length, samples_rendered, result);
620
result = get_result();
623
//printf("PackageRenderer::render_package 20\n");
625
//printf("PackageRenderer::render_package 30\n");
628
//printf("PackageRenderer::render_package 40\n");
635
//printf("PackageRenderer::render_package 50\n");
637
//printf("PackageRenderer::render_package 60\n");
641
//printf("PackageRenderer::render_package 70\n");
655
// Try to copy the compressed frame directly from the input to output files
656
// Return 1 on failure and 0 on success
657
int PackageRenderer::direct_frame_copy(EDL *edl,
658
int64_t &video_position,
662
Track *playable_track;
666
//printf("Render::direct_frame_copy 1\n");
667
if(direct_copy_possible(edl,
673
// Switch to direct copying
674
if(!direct_frame_copying)
676
if(video_write_position)
678
error |= file->write_video_buffer(video_write_position);
679
video_write_position = 0;
681
file->stop_video_thread();
682
direct_frame_copying = 1;
684
//printf("Render::direct_frame_copy 2\n");
686
if(!package->use_brender)
687
error |= ((VEdit*)playable_edit)->read_frame(compressed_output,
696
if(!error && video_preroll > 0)
703
if(package->use_brender)
705
//printf("PackageRenderer::direct_frame_copy 1\n");
706
error = set_video_map(video_position, BRender::SCANNED);
707
//printf("PackageRenderer::direct_frame_copy 10 %d\n", error);
711
VFrame ***temp_output = new VFrame**[1];
712
temp_output[0] = new VFrame*[1];
713
temp_output[0][0] = compressed_output;
714
error = file->write_frames(temp_output, 1);
715
delete [] temp_output[0];
725
int PackageRenderer::direct_copy_possible(EDL *edl,
726
int64_t current_position,
727
Track* playable_track, // The one track which is playable
728
Edit* &playable_edit, // The edit which is playing
729
File *file) // Output file
732
int total_playable_tracks = 0;
733
Track* current_track;
734
Patch* current_patch;
738
// Number of playable tracks must equal 1
739
for(current_track = edl->tracks->first;
740
current_track && result;
741
current_track = current_track->next)
743
if(current_track->data_type == TRACK_VIDEO)
745
if(playable_tracks->is_playable(current_track, current_position, 1))
747
playable_track = current_track;
748
total_playable_tracks++;
753
//printf("Render::direct_copy_possible 1 %d\n", result);
754
if(total_playable_tracks != 1) result = 0;
755
//printf("Render::direct_copy_possible 2 %d\n", result);
757
// Edit must have a source file
760
//printf("Render::direct_copy_possible 3 %d\n", result);
761
playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
762
//printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
767
// Source file must be able to copy to destination file.
768
// Source file must be same size as project output.
771
//printf("Render::direct_copy_possible 5 %d\n", result);
772
if(!file->can_copy_from(playable_edit,
773
current_position + playable_track->nudge,
774
edl->session->output_w,
775
edl->session->output_h))
778
//printf("Render::direct_copy_possible 6 %d\n", result);
780
// Test conditions mutual between vrender.C and this.
782
!playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
784
//printf("Render::direct_copy_possible 7 %d\n", result);
797
int PackageRenderer::get_master()
802
// Get result status from server
803
int PackageRenderer::get_result()
808
void PackageRenderer::set_result(int value)
812
void PackageRenderer::set_progress(int64_t value)
816
int PackageRenderer::set_video_map(int64_t position, int value)
820
int PackageRenderer::progress_cancelled()