3 #include "virtualconsole.h"
7 #include "edlsession.h"
9 #include "localsession.h"
11 #include "playbackengine.h"
12 #include "playabletracks.h"
13 #include "preferences.h"
14 #include "preferencesthread.h"
15 #include "renderengine.h"
16 #include "mainsession.h"
17 #include "strategies.inc"
20 #include "transportque.h"
24 #include "videoconfig.h"
25 #include "videodevice.h"
26 #include "virtualvconsole.h"
34 VRender::VRender(RenderEngine *renderengine)
35 : CommonRender(renderengine)
37 data_type = TRACK_VIDEO;
45 VirtualConsole* VRender::new_vconsole_object()
47 return new VirtualVConsole(renderengine, this);
50 int VRender::get_total_tracks()
52 return renderengine->edl->tracks->total_video_tracks();
55 Module* VRender::new_module(Track *track)
57 //printf("VRender::new_module\n");
58 return new VModule(renderengine, this, 0, track);
61 int VRender::flash_output()
63 //printf("VRender::flash_output 1\n");
64 return renderengine->video->write_buffer(video_out, renderengine->edl);
67 int VRender::process_buffer(VFrame **video_out,
68 int64_t input_position,
71 // process buffer for non realtime
73 int64_t render_len = 1;
77 //printf("VRender::process_buffer 1\n");
78 for(i = 0; i < MAX_CHANNELS; i++)
79 this->video_out[i] = video_out[i];
80 this->last_playback = last_buffer;
82 current_position = input_position;
83 //printf("VRender::process_buffer 2\n");
85 // test for automation configuration and shorten the fragment len if necessary
86 reconfigure = vconsole->test_reconfigure(input_position,
89 //printf("VRender::process_buffer 3\n");
91 if(reconfigure) restart_playback();
92 //printf("VRender::process_buffer 4\n");
93 return process_buffer(input_position);
97 int VRender::process_buffer(int64_t input_position)
99 Edit *playable_edit = 0;
101 int use_vconsole = 1;
104 //printf("VRender::process_buffer 1 %d\n", input_position);
106 // Determine the rendering strategy for this frame.
107 use_vconsole = get_use_vconsole(playable_edit,
111 // printf("VRender::process_buffer 1 %d %d %d\n",
116 // Negotiate color model
117 colormodel = get_colormodel(playable_edit, use_vconsole, use_brender);
119 //printf("VRender::process_buffer 2 %p %d %d\n", renderengine->video, use_vconsole, colormodel);
120 // Get output buffer from device
121 if(renderengine->command->realtime)
122 renderengine->video->new_output_buffers(video_out, colormodel);
124 //printf("VRender::process_buffer 3 %d %d\n", current_position, use_vconsole);
125 // Read directly from file to video_out
129 //printf("VRender::process_buffer 4 %d %p %p %p\n",
130 //current_position, renderengine->get_vcache(), playable_edit, video_out[0]);
133 //printf("VRender::process_buffer 4.1\n");
134 Asset *asset = renderengine->preferences->brender_asset;
135 File *file = renderengine->get_vcache()->check_out(asset);
138 int64_t corrected_position = current_position;
139 if(renderengine->command->get_direction() == PLAY_REVERSE)
140 corrected_position--;
142 file->set_video_position(corrected_position,
143 renderengine->edl->session->frame_rate);
144 file->read_frame(video_out[0]);
145 renderengine->get_vcache()->check_in(asset);
151 //printf("VRender::process_buffer 4.2\n");
152 result = ((VEdit*)playable_edit)->read_frame(video_out[0],
154 renderengine->command->get_direction(),
155 renderengine->get_vcache());
156 //printf("VRender::process_buffer 4.3\n");
159 //printf("VRender::process_buffer 5\n");
160 //for(int j = video_out[0]->get_w() * 3 * 5; j < video_out[0]->get_w() * 3 * 10; j += 2)
161 // ((u_int16_t*)video_out[0]->get_rows()[0])[j] = 0xffff;
164 // Read into virtual console
167 //printf("VRender::process_buffer 6 %d\n", input_position);
168 // process this buffer now in the virtual console
169 result = ((VirtualVConsole*)vconsole)->process_buffer(input_position);
171 //printf("VRender::process_buffer 7\n");
175 //printf("VRender::process_buffer 8\n");
179 // Determine if virtual console is needed
180 int VRender::get_use_vconsole(Edit* &playable_edit,
184 Track *playable_track;
187 // Background rendering completed
188 if((use_brender = renderengine->brender_available(position,
189 renderengine->command->get_direction())) != 0)
194 //printf("VRender::get_use_vconsole 1\n");
195 // Total number of playable tracks is 1
196 if(vconsole->total_tracks != 1) return 1;
198 playable_track = vconsole->playable_tracks->values[0];
199 //printf("VRender::get_use_vconsole 2\n");
201 // Test mutual conditions between render.C and this.
202 if(!playable_track->direct_copy_possible(position, renderengine->command->get_direction()))
205 //printf("VRender::get_use_vconsole 3\n");
206 playable_edit = playable_track->edits->editof(position, renderengine->command->get_direction());
207 // No edit at current location
208 if(!playable_edit) return 1;
211 if(!playable_edit->asset) return 1;
212 //printf("VRender::get_use_vconsole 4\n");
214 // Asset and output device must have the same dimensions
215 if(playable_edit->asset->width != renderengine->edl->session->output_w ||
216 playable_edit->asset->height != renderengine->edl->session->output_h)
218 //printf("VRender::get_use_vconsole 5\n");
220 // If we get here the frame is going to be directly copied. Whether it is
221 // decompressed in hardware depends on the colormodel.
225 int VRender::get_colormodel(Edit* &playable_edit,
229 int colormodel = renderengine->edl->session->color_model;
231 //printf("VRender::get_colormodel 1\n");
232 if(!use_vconsole && !renderengine->command->single_frame())
234 // Get best colormodel supported by the file
235 int driver = renderengine->config->vconfig->driver;
241 asset = renderengine->preferences->brender_asset;
245 asset = playable_edit->asset;
248 //printf("VRender::get_colormodel 1\n");
249 file = renderengine->get_vcache()->check_out(asset);
250 //printf("VRender::get_colormodel 10\n");
254 //printf("VRender::get_colormodel 20n");
255 colormodel = file->get_best_colormodel(driver);
256 //printf("VRender::get_colormodel 30\n");
257 renderengine->get_vcache()->check_in(asset);
258 //printf("VRender::get_colormodel 40\n");
261 //printf("VRender::get_colormodel 100\n");
274 //printf("VRender:run 1\n");
276 // Want to know how many samples rendering each frame takes.
277 // Then use this number to predict the next frame that should be rendered.
278 // Be suspicious of frames that render late so have a countdown
279 // before we start dropping.
280 int64_t current_sample, start_sample, end_sample; // Absolute counts.
281 int64_t next_frame; // Actual position.
282 int64_t last_delay = 0; // delay used before last frame
283 int64_t skip_countdown = VRENDER_THRESHOLD; // frames remaining until drop
284 int64_t delay_countdown = VRENDER_THRESHOLD; // Frames remaining until delay
285 // Number of frames before next reconfigure
286 int64_t current_input_length;
287 // Number of frames to skip.
288 int64_t frame_step = 1;
290 // Number of frames since start of rendering
292 framerate_counter = 0;
293 framerate_timer.update();
298 //printf("VRender:run 2 %d %d %d\n", done, renderengine->video->interrupt, last_playback);
300 !renderengine->video->interrupt &&
303 // Perform the most time consuming part of frame decompression now.
304 // Want the condition before, since only 1 frame is rendered
305 // and the number of frames skipped after this frame varies.
306 current_input_length = 1; // 1 frame
308 //printf("VRender:run 3 %d\n", current_position);
309 reconfigure = vconsole->test_reconfigure(current_position,
310 current_input_length,
313 //printf("VRender:run 4 %d %d\n", current_position, reconfigure);
314 if(reconfigure) restart_playback();
315 //printf("VRender:run 5 %p\n", renderengine);
317 process_buffer(current_position);
318 //printf("VRender:run 6 %p %p\n", renderengine, renderengine->video);
320 if(renderengine->command->single_frame())
322 //printf("VRender:run 7 %d\n", current_position);
326 //printf("VRender:run 8 %d\n", current_position);
329 // Perform synchronization
331 // Determine the delay until the frame needs to be shown.
332 //printf("VRender:run 9\n");
333 current_sample = (int64_t)(renderengine->sync_position() *
334 renderengine->command->get_speed());
335 // latest sample at which the frame can be shown.
336 end_sample = Units::tosamples(session_frame,
337 renderengine->edl->session->sample_rate,
338 renderengine->edl->session->frame_rate);
339 // earliest sample by which the frame needs to be shown.
340 start_sample = Units::tosamples(session_frame - 1,
341 renderengine->edl->session->sample_rate,
342 renderengine->edl->session->frame_rate);
343 //printf("VRender:run 9 current sample %d end sample %d start sample %d\n", current_sample, end_sample, start_sample);
344 //printf("VRender:run 10 everyframe %d\n", renderengine->edl->session->video_every_frame);
346 // Straight from XMovie
347 if(end_sample < current_sample)
349 // Frame rendered late. Flash it now.
352 if(renderengine->edl->session->video_every_frame)
354 // User wants every frame.
358 if(skip_countdown > 0)
360 // Maybe just a freak.
366 // Get the frames to skip.
367 delay_countdown = VRENDER_THRESHOLD;
369 frame_step += (int64_t)Units::toframes(current_sample,
370 renderengine->edl->session->sample_rate,
371 renderengine->edl->session->frame_rate);
372 frame_step -= (int64_t)Units::toframes(end_sample,
373 renderengine->edl->session->sample_rate,
374 renderengine->edl->session->frame_rate);
376 //printf("VRender:run 11 frame_step %d\n", frame_step);
380 // Frame rendered early or just in time.
383 if(delay_countdown > 0)
385 // Maybe just a freak
390 skip_countdown = VRENDER_THRESHOLD;
391 if(start_sample > current_sample)
393 // Came before the earliest sample so delay
394 timer.delay((int64_t)((float)(start_sample - current_sample) *
396 renderengine->edl->session->sample_rate));
400 // Came after the earliest sample so keep going
407 //printf("VRender:run 11\n");
410 //printf("VRender:run 12 %d\n", current_position);
412 session_frame += frame_step;
413 //printf("VRender:run 13 %d %d\n", frame_step, last_playback);
415 // advance position in project
416 current_input_length = frame_step;
417 // Subtract frame_step in a loop to allow looped playback to drain
418 while(frame_step && current_input_length && !last_playback)
420 // set last_playback if necessary and trim current_input_length to range
421 //printf("VRender:run 14 %d %d\n", current_input_length, renderengine->edl->local_session->loop_playback);
422 get_boundaries(current_input_length);
423 //printf("VRender:run 15 %d %d %d\n", frame_step, current_input_length, last_playback);
426 advance_position(current_input_length);
427 //printf("VRender:run 16 %d %d\n", frame_step, last_playback);
428 frame_step -= current_input_length;
429 current_input_length = frame_step;
433 if(renderengine->command->realtime &&
434 renderengine->playback_engine &&
435 renderengine->command->command != CURRENT_FRAME)
437 //printf("VRender:run 17 %d\n", current_position);
438 renderengine->playback_engine->update_tracking(fromunits(current_position));
441 // Calculate the framerate counter
443 if(framerate_counter >= renderengine->edl->session->frame_rate &&
444 renderengine->command->realtime)
446 //printf("VRender::run 1\n");
447 renderengine->update_framerate((float)framerate_counter /
448 ((float)framerate_timer.get_difference() / 1000));
449 //printf("VRender::run 2\n");
450 framerate_counter = 0;
451 framerate_timer.update();
453 //printf("VRender:run 13\n");
456 //printf("VRender:run 14\n");
482 VRender::VRender(MWindow *mwindow, RenderEngine *renderengine)
483 : CommonRender(mwindow, renderengine)
486 vmodule_render_fragment = 0;
489 asynchronous = 0; // render 1 frame at a time
490 framerate_counter = 0;
492 render_strategy = -1;
495 int VRender::init_device_buffers()
497 // allocate output buffer if there is a video device
498 if(renderengine->video)
501 render_strategy = -1;
505 int VRender::get_datatype()
511 int VRender::start_playback()
513 // start reading input and sending to vrenderthread
514 // use a thread only if there's a video device
515 if(renderengine->command->realtime)
521 int VRender::wait_for_startup()
531 int64_t VRender::tounits(double position, int round)
534 return Units::round(position * renderengine->edl->session->frame_rate);
536 return Units::to_int64(position * renderengine->edl->session->frame_rate);
539 double VRender::fromunits(int64_t position)
541 return (double)position / renderengine->edl->session->frame_rate;