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 for(i = 0; i < MAX_CHANNELS; i++)
00087 this->video_out[i] = video_out[i];
00088 this->last_playback = last_buffer;
00089
00090 current_position = input_position;
00091
00092
00093 reconfigure = vconsole->test_reconfigure(input_position,
00094 render_len,
00095 last_playback);
00096
00097 if(reconfigure) restart_playback();
00098 return process_buffer(input_position);
00099 }
00100
00101
00102 int VRender::process_buffer(int64_t input_position)
00103 {
00104 Edit *playable_edit = 0;
00105 int colormodel;
00106 int use_vconsole = 1;
00107 int use_brender = 0;
00108 int result = 0;
00109 SET_TRACE
00110
00111
00112 use_vconsole = get_use_vconsole(playable_edit,
00113 input_position,
00114 use_brender);
00115
00116 SET_TRACE
00117
00118 colormodel = get_colormodel(playable_edit, use_vconsole, use_brender);
00119 SET_TRACE
00120
00121
00122 if(renderengine->command->realtime)
00123 renderengine->video->new_output_buffers(video_out, colormodel);
00124 SET_TRACE
00125
00126 if(!use_vconsole)
00127 {
00128
00129 if(use_brender)
00130 {
00131 Asset *asset = renderengine->preferences->brender_asset;
00132 File *file = renderengine->get_vcache()->check_out(asset);
00133 if(file)
00134 {
00135 int64_t corrected_position = current_position;
00136 if(renderengine->command->get_direction() == PLAY_REVERSE)
00137 corrected_position--;
00138
00139
00140 if(renderengine->command->single_frame())
00141 file->set_cache_frames(1);
00142 file->set_video_position(corrected_position,
00143 renderengine->edl->session->frame_rate);
00144 file->read_frame(video_out[0]);
00145 if(renderengine->command->single_frame())
00146 file->set_cache_frames(0);
00147 renderengine->get_vcache()->check_in(asset);
00148 }
00149 }
00150 else
00151 if(playable_edit)
00152 {
00153 result = ((VEdit*)playable_edit)->read_frame(video_out[0],
00154 current_position,
00155 renderengine->command->get_direction(),
00156 renderengine->get_vcache(),
00157 1,
00158 renderengine->command->single_frame());
00159
00160 if(renderengine->show_tc)
00161 insert_timecode(playable_edit,
00162 input_position,
00163 video_out[0]);
00164 }
00165 }
00166 else
00167
00168 {
00169
00170
00171 SET_TRACE
00172 result = ((VirtualVConsole*)vconsole)->process_buffer(input_position);
00173 SET_TRACE
00174 }
00175
00176
00177 return result;
00178 }
00179
00180
00181 int VRender::get_use_vconsole(Edit* &playable_edit,
00182 int64_t position,
00183 int &use_brender)
00184 {
00185 Track *playable_track;
00186
00187
00188
00189 if((use_brender = renderengine->brender_available(position,
00190 renderengine->command->get_direction())) != 0)
00191 return 0;
00192
00193
00194
00195
00196 if(vconsole->total_entry_nodes != 1) return 1;
00197
00198 playable_track = vconsole->playable_tracks->values[0];
00199
00200
00201 if(!playable_track->direct_copy_possible(position,
00202 renderengine->command->get_direction(),
00203 1))
00204 return 1;
00205
00206 playable_edit = playable_track->edits->editof(position,
00207 renderengine->command->get_direction(),
00208 1);
00209
00210 if(!playable_edit) return 1;
00211
00212
00213 if(!playable_edit->asset) return 1;
00214
00215
00216 if(playable_edit->asset->width != renderengine->edl->session->output_w ||
00217 playable_edit->asset->height != renderengine->edl->session->output_h)
00218 return 1;
00219
00220
00221 if (ilaceautofixmethod2(renderengine->edl->session->interlace_mode,
00222 playable_edit->asset->interlace_autofixoption,
00223 playable_edit->asset->interlace_mode,
00224 playable_edit->asset->interlace_fixmethod)
00225 != BC_ILACE_FIXMETHOD_NONE)
00226 return 1;
00227
00228
00229
00230 return 0;
00231 }
00232
00233
00234 int VRender::insert_timecode(Edit* &playable_edit,
00235 int64_t position,
00236 VFrame *output)
00237 {
00238 EDLSession *session = renderengine->edl->session;
00239
00240
00241 VFrame *input = new VFrame(0,
00242 output->get_w(),
00243 MIN(output->get_h(), 50),
00244 output->get_color_model(),
00245 output->get_bytes_per_line());
00246 char etc[12];
00247 char srctc[12];
00248 int src_position = 0;
00249
00250 TRACE("VRender::insert_timecode 10")
00251
00252
00253 Units::totext(etc,
00254 (renderengine->vrender->current_position +
00255 session->get_frame_offset()) / session->frame_rate,
00256 session->time_format,
00257 session->sample_rate,
00258 session->frame_rate,
00259 session->frames_per_foot);
00260
00261 TRACE("VRender::insert_timecode 20")
00262
00263 if(playable_edit)
00264 {
00265 TRACE("VRender::insert_timecode 30")
00266 src_position = renderengine->vrender->current_position -
00267 playable_edit->startproject +
00268 playable_edit->startsource +
00269 playable_edit->asset->tcstart;
00270 TRACE("VRender::insert_timecode 40")
00271 Units::totext(srctc,
00272 src_position / playable_edit->asset->frame_rate,
00273 session->time_format,
00274 session->sample_rate,
00275 playable_edit->asset->frame_rate,
00276 session->frames_per_foot);
00277 }
00278 else
00279 {
00280 TRACE("VRender::insert_timecode 50")
00281 Units::totext(srctc,
00282 0.0,
00283
00284 session->time_format,
00285 session->sample_rate,
00286 session->frame_rate,
00287 session->frames_per_foot);
00288 }
00289 TRACE("VRender::insert_timecode 60")
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 delete(input);
00315 UNTRACE
00316 }
00317
00318
00319 int VRender::get_colormodel(Edit* &playable_edit,
00320 int use_vconsole,
00321 int use_brender)
00322 {
00323 SET_TRACE
00324 int colormodel = renderengine->edl->session->color_model;
00325
00326 SET_TRACE
00327 if(!use_vconsole && !renderengine->command->single_frame())
00328 {
00329
00330 SET_TRACE
00331 int driver = renderengine->config->vconfig->driver;
00332 SET_TRACE
00333 File *file;
00334 Asset *asset;
00335
00336 if(use_brender)
00337 {
00338 asset = renderengine->preferences->brender_asset;
00339 }
00340 else
00341 {
00342 asset = playable_edit->asset;
00343 }
00344
00345 SET_TRACE
00346 file = renderengine->get_vcache()->check_out(asset);
00347 SET_TRACE
00348
00349 if(file)
00350 {
00351 colormodel = file->get_best_colormodel(driver);
00352 renderengine->get_vcache()->check_in(asset);
00353 }
00354 SET_TRACE
00355 }
00356 return colormodel;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365 void VRender::run()
00366 {
00367 int reconfigure;
00368
00369
00370
00371
00372
00373 int64_t current_sample, start_sample, end_sample;
00374 int64_t next_frame;
00375 int64_t last_delay = 0;
00376 int64_t skip_countdown = VRENDER_THRESHOLD;
00377 int64_t delay_countdown = VRENDER_THRESHOLD;
00378
00379 int64_t current_input_length;
00380
00381 int64_t frame_step = 1;
00382
00383 first_frame = 1;
00384
00385
00386 session_frame = 0;
00387 framerate_counter = 0;
00388 framerate_timer.update();
00389
00390 start_lock->unlock();
00391
00392
00393 while(!done &&
00394 !renderengine->video->interrupt &&
00395 !last_playback)
00396 {
00397 TRACE("VRender::run 0");
00398
00399
00400
00401 current_input_length = 1;
00402
00403 reconfigure = vconsole->test_reconfigure(current_position,
00404 current_input_length,
00405 last_playback);
00406 TRACE("VRender::run 0.1");
00407
00408 if(reconfigure) restart_playback();
00409 TRACE("VRender::run 0.2");
00410
00411 process_buffer(current_position);
00412
00413 TRACE("VRender::run 0.3");
00414 if(renderengine->command->single_frame())
00415 {
00416
00417 flash_output();
00418
00419 frame_step = 1;
00420 done = 1;
00421 }
00422 else
00423
00424 {
00425 TRACE("VRender::run 0.4");
00426
00427 current_sample = (int64_t)(renderengine->sync_position() *
00428 renderengine->command->get_speed());
00429 TRACE("VRender::run 0.5");
00430
00431 end_sample = Units::tosamples(session_frame,
00432 renderengine->edl->session->sample_rate,
00433 renderengine->edl->session->frame_rate);
00434
00435 start_sample = Units::tosamples(session_frame - 1,
00436 renderengine->edl->session->sample_rate,
00437 renderengine->edl->session->frame_rate);
00438
00439 if(first_frame || end_sample < current_sample)
00440 {
00441
00442 flash_output();
00443
00444 if(renderengine->edl->session->video_every_frame)
00445 {
00446
00447 frame_step = 1;
00448 }
00449 else
00450 if(skip_countdown > 0)
00451 {
00452
00453 frame_step = 1;
00454 skip_countdown--;
00455 }
00456 else
00457 {
00458
00459 delay_countdown = VRENDER_THRESHOLD;
00460 frame_step = 1;
00461 frame_step += (int64_t)Units::toframes(current_sample,
00462 renderengine->edl->session->sample_rate,
00463 renderengine->edl->session->frame_rate);
00464 frame_step -= (int64_t)Units::toframes(end_sample,
00465 renderengine->edl->session->sample_rate,
00466 renderengine->edl->session->frame_rate);
00467 }
00468
00469
00470 }
00471 else
00472 {
00473
00474 frame_step = 1;
00475
00476
00477 if(delay_countdown > 0)
00478 {
00479
00480 delay_countdown--;
00481 }
00482 else
00483 {
00484 skip_countdown = VRENDER_THRESHOLD;
00485 if(start_sample > current_sample)
00486 {
00487 int64_t delay_time = (int64_t)((float)(start_sample - current_sample) *
00488 1000 /
00489 renderengine->edl->session->sample_rate);
00490 timer.delay(delay_time);
00491
00492 }
00493 else
00494 {
00495
00496 }
00497 }
00498
00499
00500
00501 flash_output();
00502
00503 }
00504 }
00505
00506
00507 if(first_frame)
00508 {
00509 renderengine->first_frame_lock->unlock();
00510 first_frame = 0;
00511 renderengine->reset_sync_position();
00512 }
00513
00514
00515 session_frame += frame_step;
00516
00517
00518 current_input_length = frame_step;
00519
00520
00521
00522 while(frame_step && current_input_length && !last_playback)
00523 {
00524
00525 get_boundaries(current_input_length);
00526
00527 advance_position(current_input_length);
00528 frame_step -= current_input_length;
00529 current_input_length = frame_step;
00530 }
00531 TRACE("VRender::run 6");
00532
00533
00534 if(renderengine->command->realtime &&
00535 renderengine->playback_engine &&
00536 renderengine->command->command != CURRENT_FRAME)
00537 {
00538 renderengine->playback_engine->update_tracking(fromunits(current_position));
00539 }
00540
00541 TRACE("VRender::run 7");
00542
00543 framerate_counter++;
00544 if(framerate_counter >= renderengine->edl->session->frame_rate &&
00545 renderengine->command->realtime)
00546 {
00547 renderengine->update_framerate((float)framerate_counter /
00548 ((float)framerate_timer.get_difference() / 1000));
00549 framerate_counter = 0;
00550 framerate_timer.update();
00551 }
00552 TRACE("VRender::run 8");
00553 }
00554 TRACE("VRender::run 10");
00555
00556
00557 renderengine->first_frame_lock->unlock();
00558
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] = 0;
00594 render_strategy = -1;
00595 }
00596
00597 int VRender::init_device_buffers()
00598 {
00599
00600 if(renderengine->video)
00601 {
00602 video_out[0] = 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 }