00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "cache.h"
00004 #include "clip.h"
00005 #include "condition.h"
00006 #include "datatype.h"
00007 #include "edits.h"
00008 #include "edl.h"
00009 #include "edlsession.h"
00010 #include "file.h"
00011 #include "interlacemodes.h"
00012 #include "localsession.h"
00013 #include "mainsession.h"
00014 #include "mwindow.h"
00015 #include "overlayframe.h"
00016 #include "playabletracks.h"
00017 #include "playbackengine.h"
00018 #include "preferences.h"
00019 #include "preferencesthread.h"
00020 #include "renderengine.h"
00021 #include "strategies.inc"
00022 #include "tracks.h"
00023 #include "transportque.h"
00024 #include "units.h"
00025 #include "vedit.h"
00026 #include "vframe.h"
00027 #include "videoconfig.h"
00028 #include "videodevice.h"
00029 #include "virtualconsole.h"
00030 #include "virtualvconsole.h"
00031 #include "vmodule.h"
00032 #include "vrender.h"
00033 #include "vtrack.h"
00034
00035
00036
00037
00038
00039 VRender::VRender(RenderEngine *renderengine)
00040 : CommonRender(renderengine)
00041 {
00042 data_type = TRACK_VIDEO;
00043 transition_temp = 0;
00044 overlayer = new OverlayFrame(renderengine->preferences->processors);
00045 input_temp = 0;
00046 }
00047
00048 VRender::~VRender()
00049 {
00050 if(input_temp) delete input_temp;
00051 if(transition_temp) delete transition_temp;
00052 if(overlayer) delete overlayer;
00053 }
00054
00055
00056 VirtualConsole* VRender::new_vconsole_object()
00057 {
00058 return new VirtualVConsole(renderengine, this);
00059 }
00060
00061 int VRender::get_total_tracks()
00062 {
00063 return renderengine->edl->tracks->total_video_tracks();
00064 }
00065
00066 Module* VRender::new_module(Track *track)
00067 {
00068 return new VModule(renderengine, this, 0, track);
00069 }
00070
00071 int VRender::flash_output()
00072 {
00073 return renderengine->video->write_buffer(video_out, renderengine->edl);
00074 }
00075
00076 int VRender::process_buffer(VFrame *video_out,
00077 int64_t input_position,
00078 int last_buffer)
00079 {
00080
00081 int i, j;
00082 int64_t render_len = 1;
00083 int reconfigure = 0;
00084
00085
00086 this->video_out = video_out;
00087 this->last_playback = last_buffer;
00088
00089 current_position = input_position;
00090
00091
00092 reconfigure = vconsole->test_reconfigure(input_position,
00093 render_len,
00094 last_playback);
00095
00096 if(reconfigure) restart_playback();
00097 return process_buffer(input_position);
00098 }
00099
00100
00101 int VRender::process_buffer(int64_t input_position)
00102 {
00103 SET_TRACE
00104 Edit *playable_edit = 0;
00105 int colormodel;
00106 int use_vconsole = 1;
00107 int use_brender = 0;
00108 int result = 0;
00109 int use_cache = renderengine->command->single_frame();
00110 int use_asynchronous =
00111 renderengine->command->realtime &&
00112 renderengine->edl->session->video_asynchronous;
00113 SET_TRACE
00114
00115
00116 use_vconsole = get_use_vconsole(playable_edit,
00117 input_position,
00118 use_brender);
00119
00120
00121 colormodel = get_colormodel(playable_edit, use_vconsole, use_brender);
00122
00123
00124 if(renderengine->command->realtime)
00125 renderengine->video->new_output_buffer(&video_out, colormodel);
00126
00127
00128
00129
00130
00131
00132
00133 if(!use_vconsole)
00134 {
00135
00136 if(use_brender)
00137 {
00138 SET_TRACE
00139 Asset *asset = renderengine->preferences->brender_asset;
00140 File *file = renderengine->get_vcache()->check_out(asset,
00141 renderengine->edl);
00142 if(file)
00143 {
00144 int64_t corrected_position = current_position;
00145 if(renderengine->command->get_direction() == PLAY_REVERSE)
00146 corrected_position--;
00147
00148
00149 if(use_asynchronous)
00150 file->start_video_decode_thread();
00151 else
00152 file->stop_video_thread();
00153 if(use_cache) file->set_cache_frames(1);
00154 file->set_video_position(corrected_position,
00155 renderengine->edl->session->frame_rate);
00156 file->read_frame(video_out);
00157 if(use_cache) file->set_cache_frames(0);
00158 renderengine->get_vcache()->check_in(asset);
00159 }
00160 SET_TRACE
00161 }
00162 else
00163 if(playable_edit)
00164 {
00165 result = ((VEdit*)playable_edit)->read_frame(video_out,
00166 current_position,
00167 renderengine->command->get_direction(),
00168 renderengine->get_vcache(),
00169 1,
00170 use_cache,
00171 use_asynchronous);
00172
00173 if(renderengine->show_tc)
00174 insert_timecode(playable_edit,
00175 input_position,
00176 video_out);
00177 }
00178 }
00179 else
00180
00181 {
00182
00183
00184 result = ((VirtualVConsole*)vconsole)->process_buffer(input_position);
00185 }
00186
00187
00188 return result;
00189 }
00190
00191
00192 int VRender::get_use_vconsole(Edit* &playable_edit,
00193 int64_t position,
00194 int &use_brender)
00195 {
00196 Track *playable_track;
00197
00198
00199
00200 if((use_brender = renderengine->brender_available(position,
00201 renderengine->command->get_direction())) != 0)
00202 return 0;
00203
00204
00205
00206
00207 if(vconsole->total_exit_nodes != 1) return 1;
00208
00209 playable_track = vconsole->playable_tracks->values[0];
00210
00211
00212 if(!playable_track->direct_copy_possible(position,
00213 renderengine->command->get_direction(),
00214 1))
00215 return 1;
00216
00217 playable_edit = playable_track->edits->editof(position,
00218 renderengine->command->get_direction(),
00219 1);
00220
00221 if(!playable_edit) return 1;
00222
00223
00224 if(!playable_edit->asset) return 1;
00225
00226
00227 if(playable_edit->asset->width != renderengine->edl->session->output_w ||
00228 playable_edit->asset->height != renderengine->edl->session->output_h)
00229 return 1;
00230
00231
00232 if (ilaceautofixmethod2(renderengine->edl->session->interlace_mode,
00233 playable_edit->asset->interlace_autofixoption,
00234 playable_edit->asset->interlace_mode,
00235 playable_edit->asset->interlace_fixmethod)
00236 != BC_ILACE_FIXMETHOD_NONE)
00237 return 1;
00238
00239
00240
00241 return 0;
00242 }
00243
00244
00245 int VRender::insert_timecode(Edit* &playable_edit,
00246 int64_t position,
00247 VFrame *output)
00248 {
00249 EDLSession *session = renderengine->edl->session;
00250
00251
00252 VFrame *input = new VFrame(0,
00253 output->get_w(),
00254 MIN(output->get_h(), 50),
00255 output->get_color_model(),
00256 output->get_bytes_per_line());
00257 char etc[12];
00258 char srctc[12];
00259 int src_position = 0;
00260
00261 TRACE("VRender::insert_timecode 10")
00262
00263
00264 Units::totext(etc,
00265 (renderengine->vrender->current_position +
00266 session->get_frame_offset()) / session->frame_rate,
00267 session->time_format,
00268 session->sample_rate,
00269 session->frame_rate,
00270 session->frames_per_foot);
00271
00272 TRACE("VRender::insert_timecode 20")
00273
00274 if(playable_edit)
00275 {
00276 TRACE("VRender::insert_timecode 30")
00277 src_position = renderengine->vrender->current_position -
00278 playable_edit->startproject +
00279 playable_edit->startsource +
00280 playable_edit->asset->tcstart;
00281 TRACE("VRender::insert_timecode 40")
00282 Units::totext(srctc,
00283 src_position / playable_edit->asset->frame_rate,
00284 session->time_format,
00285 session->sample_rate,
00286 playable_edit->asset->frame_rate,
00287 session->frames_per_foot);
00288 }
00289 else
00290 {
00291 TRACE("VRender::insert_timecode 50")
00292 Units::totext(srctc,
00293 0.0,
00294
00295 session->time_format,
00296 session->sample_rate,
00297 session->frame_rate,
00298 session->frames_per_foot);
00299 }
00300 TRACE("VRender::insert_timecode 60")
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 delete(input);
00326 UNTRACE
00327 }
00328
00329
00330 int VRender::get_colormodel(Edit* &playable_edit,
00331 int use_vconsole,
00332 int use_brender)
00333 {
00334 int colormodel = renderengine->edl->session->color_model;
00335
00336 if(!use_vconsole && !renderengine->command->single_frame())
00337 {
00338
00339 int driver = renderengine->config->vconfig->driver;
00340 File *file;
00341 Asset *asset;
00342
00343 if(use_brender)
00344 {
00345 asset = renderengine->preferences->brender_asset;
00346 }
00347 else
00348 {
00349 asset = playable_edit->asset;
00350 }
00351
00352 file = renderengine->get_vcache()->check_out(asset,
00353 renderengine->edl);
00354
00355 if(file)
00356 {
00357 colormodel = file->get_best_colormodel(driver);
00358 renderengine->get_vcache()->check_in(asset);
00359 }
00360 }
00361
00362 return colormodel;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 void VRender::run()
00372 {
00373 int reconfigure;
00374
00375
00376
00377
00378
00379 int64_t current_sample, start_sample, end_sample;
00380 int64_t next_frame;
00381 int64_t last_delay = 0;
00382 int64_t skip_countdown = VRENDER_THRESHOLD;
00383 int64_t delay_countdown = VRENDER_THRESHOLD;
00384
00385 int64_t current_input_length;
00386
00387 int64_t frame_step = 1;
00388
00389 first_frame = 1;
00390
00391
00392 session_frame = 0;
00393 framerate_counter = 0;
00394 framerate_timer.update();
00395
00396 start_lock->unlock();
00397
00398
00399 while(!done &&
00400 !renderengine->video->interrupt &&
00401 !last_playback)
00402 {
00403
00404
00405
00406 current_input_length = 1;
00407
00408 reconfigure = vconsole->test_reconfigure(current_position,
00409 current_input_length,
00410 last_playback);
00411
00412 if(reconfigure) restart_playback();
00413
00414 SET_TRACE
00415 process_buffer(current_position);
00416 SET_TRACE
00417
00418 if(renderengine->command->single_frame())
00419 {
00420 flash_output();
00421 frame_step = 1;
00422 done = 1;
00423 }
00424 else
00425
00426 {
00427 SET_TRACE
00428
00429 current_sample = (int64_t)(renderengine->sync_position() *
00430 renderengine->command->get_speed());
00431
00432 end_sample = Units::tosamples(session_frame,
00433 renderengine->edl->session->sample_rate,
00434 renderengine->edl->session->frame_rate);
00435
00436 start_sample = Units::tosamples(session_frame - 1,
00437 renderengine->edl->session->sample_rate,
00438 renderengine->edl->session->frame_rate);
00439 SET_TRACE
00440
00441 if(first_frame || end_sample < current_sample)
00442 {
00443 SET_TRACE
00444
00445 flash_output();
00446 SET_TRACE
00447
00448 if(renderengine->edl->session->video_every_frame)
00449 {
00450
00451 frame_step = 1;
00452 }
00453 else
00454 if(skip_countdown > 0)
00455 {
00456
00457 frame_step = 1;
00458 skip_countdown--;
00459 }
00460 else
00461 {
00462
00463 delay_countdown = VRENDER_THRESHOLD;
00464 frame_step = 1;
00465 frame_step += (int64_t)Units::toframes(current_sample,
00466 renderengine->edl->session->sample_rate,
00467 renderengine->edl->session->frame_rate);
00468 frame_step -= (int64_t)Units::toframes(end_sample,
00469 renderengine->edl->session->sample_rate,
00470 renderengine->edl->session->frame_rate);
00471 }
00472 }
00473 else
00474 {
00475
00476 frame_step = 1;
00477 SET_TRACE
00478
00479 if(delay_countdown > 0)
00480 {
00481
00482 delay_countdown--;
00483 }
00484 else
00485 {
00486 skip_countdown = VRENDER_THRESHOLD;
00487 if(start_sample > current_sample)
00488 {
00489 SET_TRACE
00490 int64_t delay_time = (int64_t)((float)(start_sample - current_sample) *
00491 1000 /
00492 renderengine->edl->session->sample_rate);
00493 SET_TRACE
00494 timer.delay(delay_time);
00495 SET_TRACE
00496 }
00497 else
00498 {
00499
00500 }
00501 }
00502
00503
00504 SET_TRACE
00505 flash_output();
00506 SET_TRACE
00507 }
00508 }
00509
00510
00511 if(first_frame)
00512 {
00513 renderengine->first_frame_lock->unlock();
00514 first_frame = 0;
00515 renderengine->reset_sync_position();
00516 }
00517
00518 session_frame += frame_step;
00519
00520
00521 current_input_length = frame_step;
00522
00523
00524
00525 while(frame_step && current_input_length && !last_playback)
00526 {
00527
00528 get_boundaries(current_input_length);
00529
00530 advance_position(current_input_length);
00531 frame_step -= current_input_length;
00532 current_input_length = frame_step;
00533 }
00534
00535
00536 if(renderengine->command->realtime &&
00537 renderengine->playback_engine &&
00538 renderengine->command->command != CURRENT_FRAME)
00539 {
00540 renderengine->playback_engine->update_tracking(fromunits(current_position));
00541 }
00542
00543
00544 framerate_counter++;
00545 if(framerate_counter >= renderengine->edl->session->frame_rate &&
00546 renderengine->command->realtime)
00547 {
00548 renderengine->update_framerate((float)framerate_counter /
00549 ((float)framerate_timer.get_difference() / 1000));
00550 framerate_counter = 0;
00551 framerate_timer.update();
00552 }
00553 }
00554
00555 SET_TRACE
00556
00557 renderengine->first_frame_lock->unlock();
00558 stop_plugins();
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 VRender::VRender(MWindow *mwindow, RenderEngine *renderengine)
00585 : CommonRender(mwindow, renderengine)
00586 {
00587 input_length = 0;
00588 vmodule_render_fragment = 0;
00589 playback_buffer = 0;
00590 session_frame = 0;
00591 asynchronous = 0;
00592 framerate_counter = 0;
00593 video_out = 0;
00594 render_strategy = -1;
00595 }
00596
00597 int VRender::init_device_buffers()
00598 {
00599
00600 if(renderengine->video)
00601 {
00602 video_out = 0;
00603 render_strategy = -1;
00604 }
00605 }
00606
00607 int VRender::get_datatype()
00608 {
00609 return TRACK_VIDEO;
00610 }
00611
00612
00613 int VRender::start_playback()
00614 {
00615
00616
00617 if(renderengine->command->realtime)
00618 {
00619 start();
00620 }
00621 }
00622
00623 int VRender::wait_for_startup()
00624 {
00625 }
00626
00627
00628
00629
00630
00631
00632
00633 int64_t VRender::tounits(double position, int round)
00634 {
00635 if(round)
00636 return Units::round(position * renderengine->edl->session->frame_rate);
00637 else
00638 return Units::to_int64(position * renderengine->edl->session->frame_rate);
00639 }
00640
00641 double VRender::fromunits(int64_t position)
00642 {
00643 return (double)position / renderengine->edl->session->frame_rate;
00644 }