4 #include "virtualconsole.h"
8 #include "edlsession.h"
10 #include "localsession.h"
12 #include "playbackengine.h"
13 #include "playabletracks.h"
14 #include "preferences.h"
15 #include "preferencesthread.h"
16 #include "renderengine.h"
17 #include "mainsession.h"
18 #include "strategies.inc"
21 #include "transportque.h"
25 #include "videoconfig.h"
26 #include "videodevice.h"
27 #include "virtualvconsole.h"
35 VRender::VRender(RenderEngine *renderengine)
36 : CommonRender(renderengine)
38 data_type = TRACK_VIDEO;
46 VirtualConsole* VRender::new_vconsole_object()
48 return new VirtualVConsole(renderengine, this);
51 int VRender::get_total_tracks()
53 return renderengine->edl->tracks->total_video_tracks();
56 Module* VRender::new_module(Track *track)
58 return new VModule(renderengine, this, 0, track);
61 int VRender::flash_output()
63 return renderengine->video->write_buffer(video_out, renderengine->edl);
66 int VRender::process_buffer(VFrame **video_out,
67 int64_t input_position,
70 // process buffer for non realtime
72 int64_t render_len = 1;
76 for(i = 0; i < MAX_CHANNELS; i++)
77 this->video_out[i] = video_out[i];
78 this->last_playback = last_buffer;
80 current_position = input_position;
82 // test for automation configuration and shorten the fragment len if necessary
83 reconfigure = vconsole->test_reconfigure(input_position,
87 if(reconfigure) restart_playback();
88 return process_buffer(input_position);
92 int VRender::process_buffer(int64_t input_position)
94 Edit *playable_edit = 0;
100 // Determine the rendering strategy for this frame.
101 use_vconsole = get_use_vconsole(playable_edit,
106 // Negotiate color model
107 colormodel = get_colormodel(playable_edit, use_vconsole, use_brender);
109 // Get output buffer from device
110 if(renderengine->command->realtime)
111 renderengine->video->new_output_buffers(video_out, colormodel);
113 // Read directly from file to video_out
119 Asset *asset = renderengine->preferences->brender_asset;
120 File *file = renderengine->get_vcache()->check_out(asset);
123 int64_t corrected_position = current_position;
124 if(renderengine->command->get_direction() == PLAY_REVERSE)
125 corrected_position--;
127 file->set_video_position(corrected_position,
128 renderengine->edl->session->frame_rate);
129 file->read_frame(video_out[0]);
130 renderengine->get_vcache()->check_in(asset);
136 //printf("VRender::process_buffer 1 %d\n", current_position);
137 result = ((VEdit*)playable_edit)->read_frame(video_out[0],
139 renderengine->command->get_direction(),
140 renderengine->get_vcache(),
145 // Read into virtual console
148 // process this buffer now in the virtual console
149 result = ((VirtualVConsole*)vconsole)->process_buffer(input_position);
157 // Determine if virtual console is needed
158 int VRender::get_use_vconsole(Edit* &playable_edit,
162 Track *playable_track;
165 // Background rendering completed
166 if((use_brender = renderengine->brender_available(position,
167 renderengine->command->get_direction())) != 0)
172 // Total number of playable tracks is 1
173 if(vconsole->total_tracks != 1) return 1;
175 playable_track = vconsole->playable_tracks->values[0];
177 // Test mutual conditions between render.C and this.
178 if(!playable_track->direct_copy_possible(position,
179 renderengine->command->get_direction(),
183 playable_edit = playable_track->edits->editof(position,
184 renderengine->command->get_direction(),
186 // No edit at current location
187 if(!playable_edit) return 1;
190 if(!playable_edit->asset) return 1;
192 // Asset and output device must have the same dimensions
193 if(playable_edit->asset->width != renderengine->edl->session->output_w ||
194 playable_edit->asset->height != renderengine->edl->session->output_h)
197 // If we get here the frame is going to be directly copied. Whether it is
198 // decompressed in hardware depends on the colormodel.
202 int VRender::get_colormodel(Edit* &playable_edit,
206 int colormodel = renderengine->edl->session->color_model;
208 //printf("VRender::get_colormodel 1\n");
209 if(!use_vconsole && !renderengine->command->single_frame())
211 // Get best colormodel supported by the file
212 int driver = renderengine->config->vconfig->driver;
218 asset = renderengine->preferences->brender_asset;
222 asset = playable_edit->asset;
225 //printf("VRender::get_colormodel 1\n");
226 file = renderengine->get_vcache()->check_out(asset);
227 //printf("VRender::get_colormodel 10\n");
231 //printf("VRender::get_colormodel 20n");
232 colormodel = file->get_best_colormodel(driver);
233 //printf("VRender::get_colormodel 30\n");
234 renderengine->get_vcache()->check_in(asset);
235 //printf("VRender::get_colormodel 40\n");
238 //printf("VRender::get_colormodel 100\n");
252 // Want to know how many samples rendering each frame takes.
253 // Then use this number to predict the next frame that should be rendered.
254 // Be suspicious of frames that render late so have a countdown
255 // before we start dropping.
256 int64_t current_sample, start_sample, end_sample; // Absolute counts.
257 int64_t next_frame; // Actual position.
258 int64_t last_delay = 0; // delay used before last frame
259 int64_t skip_countdown = VRENDER_THRESHOLD; // frames remaining until drop
260 int64_t delay_countdown = VRENDER_THRESHOLD; // Frames remaining until delay
261 // Number of frames before next reconfigure
262 int64_t current_input_length;
263 // Number of frames to skip.
264 int64_t frame_step = 1;
266 // Number of frames since start of rendering
268 framerate_counter = 0;
269 framerate_timer.update();
271 start_lock->unlock();
275 !renderengine->video->interrupt &&
278 // Perform the most time consuming part of frame decompression now.
279 // Want the condition before, since only 1 frame is rendered
280 // and the number of frames skipped after this frame varies.
281 current_input_length = 1;
283 reconfigure = vconsole->test_reconfigure(current_position,
284 current_input_length,
287 if(reconfigure) restart_playback();
289 process_buffer(current_position);
291 if(renderengine->command->single_frame())
298 // Perform synchronization
300 // Determine the delay until the frame needs to be shown.
301 current_sample = (int64_t)(renderengine->sync_position() *
302 renderengine->command->get_speed());
303 // latest sample at which the frame can be shown.
304 end_sample = Units::tosamples(session_frame,
305 renderengine->edl->session->sample_rate,
306 renderengine->edl->session->frame_rate);
307 // earliest sample by which the frame needs to be shown.
308 start_sample = Units::tosamples(session_frame - 1,
309 renderengine->edl->session->sample_rate,
310 renderengine->edl->session->frame_rate);
311 // printf("VRender:run 9 currentsample=%lld endsample=%lld startsample=%lld samplerate=%lld framerate=%f\n",
315 // renderengine->edl->session->sample_rate,
316 // renderengine->edl->session->frame_rate);
318 // Straight from XMovie
319 if(end_sample < current_sample)
321 // Frame rendered late. Flash it now.
324 if(renderengine->edl->session->video_every_frame)
326 // User wants every frame.
330 if(skip_countdown > 0)
332 // Maybe just a freak.
338 // Get the frames to skip.
339 delay_countdown = VRENDER_THRESHOLD;
341 frame_step += (int64_t)Units::toframes(current_sample,
342 renderengine->edl->session->sample_rate,
343 renderengine->edl->session->frame_rate);
344 frame_step -= (int64_t)Units::toframes(end_sample,
345 renderengine->edl->session->sample_rate,
346 renderengine->edl->session->frame_rate);
348 //printf("VRender:run 11 frame_step %d\n", frame_step);
352 // Frame rendered early or just in time.
355 if(delay_countdown > 0)
357 // Maybe just a freak
362 skip_countdown = VRENDER_THRESHOLD;
363 if(start_sample > current_sample)
365 int64_t delay_time = (int64_t)((float)(start_sample - current_sample) *
367 renderengine->edl->session->sample_rate);
368 timer.delay(delay_time);
369 //printf("VRender:run 10 %lld\n", delay_time);
373 // Came after the earliest sample so keep going
375 //printf("VRender:run 20\n");
381 //printf("VRender:run 11\n");
384 //printf("VRender:run 12 %d\n", current_position);
386 session_frame += frame_step;
387 //printf("VRender:run 13 %d %d\n", frame_step, last_playback);
389 // advance position in project
390 current_input_length = frame_step;
393 // Subtract frame_step in a loop to allow looped playback to drain
394 while(frame_step && current_input_length && !last_playback)
396 // set last_playback if necessary and trim current_input_length to range
397 get_boundaries(current_input_length);
399 advance_position(current_input_length);
400 frame_step -= current_input_length;
401 current_input_length = frame_step;
405 if(renderengine->command->realtime &&
406 renderengine->playback_engine &&
407 renderengine->command->command != CURRENT_FRAME)
409 //printf("VRender:run 17 %d\n", current_position);
410 renderengine->playback_engine->update_tracking(fromunits(current_position));
413 // Calculate the framerate counter
415 if(framerate_counter >= renderengine->edl->session->frame_rate &&
416 renderengine->command->realtime)
418 //printf("VRender::run 1\n");
419 renderengine->update_framerate((float)framerate_counter /
420 ((float)framerate_timer.get_difference() / 1000));
421 //printf("VRender::run 2\n");
422 framerate_counter = 0;
423 framerate_timer.update();
425 //printf("VRender:run 13\n");
428 //printf("VRender:run 14\n");
454 VRender::VRender(MWindow *mwindow, RenderEngine *renderengine)
455 : CommonRender(mwindow, renderengine)
458 vmodule_render_fragment = 0;
461 asynchronous = 0; // render 1 frame at a time
462 framerate_counter = 0;
464 render_strategy = -1;
467 int VRender::init_device_buffers()
469 // allocate output buffer if there is a video device
470 if(renderengine->video)
473 render_strategy = -1;
477 int VRender::get_datatype()
483 int VRender::start_playback()
485 // start reading input and sending to vrenderthread
486 // use a thread only if there's a video device
487 if(renderengine->command->realtime)
493 int VRender::wait_for_startup()
503 int64_t VRender::tounits(double position, int round)
506 return Units::round(position * renderengine->edl->session->frame_rate);
508 return Units::to_int64(position * renderengine->edl->session->frame_rate);
511 double VRender::fromunits(int64_t position)
513 return (double)position / renderengine->edl->session->frame_rate;