Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

vrender.C

Go to the documentation of this file.
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 // process buffer for non realtime
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 // test for automation configuration and shorten the fragment len if necessary
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 // Determine the rendering strategy for this frame.
00112         use_vconsole = get_use_vconsole(playable_edit, 
00113                 input_position,
00114                 use_brender);
00115 
00116 SET_TRACE
00117 // Negotiate color model
00118         colormodel = get_colormodel(playable_edit, use_vconsole, use_brender);
00119 SET_TRACE
00120 
00121 // Get output buffer from device
00122         if(renderengine->command->realtime)
00123                 renderengine->video->new_output_buffers(video_out, colormodel);
00124 SET_TRACE
00125 // Read directly from file to video_out
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 // Cache single frames only
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                                                 /* Insert timecode */
00160                         if(renderengine->show_tc)
00161                                 insert_timecode(playable_edit,
00162                                         input_position,
00163                                         video_out[0]);
00164                 }
00165         }
00166         else
00167 // Read into virtual console
00168         {
00169 
00170 // process this buffer now in the virtual console
00171 SET_TRACE
00172                 result = ((VirtualVConsole*)vconsole)->process_buffer(input_position);
00173 SET_TRACE
00174         }
00175 
00176 
00177         return result;
00178 }
00179 
00180 // Determine if virtual console is needed
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 // Background rendering completed
00189         if((use_brender = renderengine->brender_available(position, 
00190                 renderengine->command->get_direction())) != 0) 
00191                 return 0;
00192 
00193 
00194 
00195 // Total number of playable tracks is 1
00196         if(vconsole->total_entry_nodes != 1) return 1;
00197 
00198         playable_track = vconsole->playable_tracks->values[0];
00199 
00200 // Test mutual conditions between render.C and this.
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 // No edit at current location
00210         if(!playable_edit) return 1;
00211 
00212 // Edit is silence
00213         if(!playable_edit->asset) return 1;
00214 
00215 // Asset and output device must have the same dimensions
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 // Asset and output device must have same resulting de-interlacing method
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 // If we get here the frame is going to be directly copied.  Whether it is
00229 // decompressed in hardware depends on the colormodel.
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         /* Create a vframe with TC and SRC timecode in white
00240          * with a black border */
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         /* Edited TC */
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 //                      (renderengine->vrender->current_position - position) / session->frame_rate,
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 //printf("re position %i position %i\n", 
00292 //      renderengine->vrender->current_position, position);
00293 //printf("SRC %s   TC %s\n", srctc, etc);
00294 
00295         /* Insert the timecode data onto the input frame */
00296         
00297         
00298 
00299 /*
00300         vrender->overlayer->overlay(output, 
00301                 input,
00302                 input->x, 
00303                 input->y, 
00304                 input->width, 
00305                 input->height,
00306                 output->x, 
00307                 output->y, 
00308                 output->width, 
00309                 output->height, 
00310                 1,
00311                 TRANSFER_REPLACE, 
00312                 renderengine->edl->session->interpolation_type);
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 // Get best colormodel supported by the file
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 // Want to know how many samples rendering each frame takes.
00370 // Then use this number to predict the next frame that should be rendered.
00371 // Be suspicious of frames that render late so have a countdown
00372 // before we start dropping.
00373         int64_t current_sample, start_sample, end_sample; // Absolute counts.
00374         int64_t next_frame;  // Actual position.
00375         int64_t last_delay = 0;  // delay used before last frame
00376         int64_t skip_countdown = VRENDER_THRESHOLD;    // frames remaining until drop
00377         int64_t delay_countdown = VRENDER_THRESHOLD;  // Frames remaining until delay
00378 // Number of frames before next reconfigure
00379         int64_t current_input_length;
00380 // Number of frames to skip.
00381         int64_t frame_step = 1;
00382 
00383         first_frame = 1;
00384 
00385 // Number of frames since start of rendering
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 // Perform the most time consuming part of frame decompression now.
00399 // Want the condition before, since only 1 frame is rendered 
00400 // and the number of frames skipped after this frame varies.
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 //TRACE("VRender::run 2");
00417                         flash_output();
00418 //TRACE("VRender::run 3");
00419                         frame_step = 1;
00420                         done = 1;
00421                 }
00422                 else
00423 // Perform synchronization
00424                 {
00425 TRACE("VRender::run 0.4");
00426 // Determine the delay until the frame needs to be shown.
00427                         current_sample = (int64_t)(renderengine->sync_position() * 
00428                                 renderengine->command->get_speed());
00429 TRACE("VRender::run 0.5");
00430 // latest sample at which the frame can be shown.
00431                         end_sample = Units::tosamples(session_frame, 
00432                                 renderengine->edl->session->sample_rate, 
00433                                 renderengine->edl->session->frame_rate);
00434 // earliest sample by which the frame needs to be shown.
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 // Frame rendered late or this is the first frame.  Flash it now.
00442                                 flash_output();
00443 
00444                                 if(renderengine->edl->session->video_every_frame)
00445                                 {
00446 // User wants every frame.
00447                                         frame_step = 1;
00448                                 }
00449                                 else
00450                                 if(skip_countdown > 0)
00451                                 {
00452 // Maybe just a freak.
00453                                         frame_step = 1;
00454                                         skip_countdown--;
00455                                 }
00456                                 else
00457                                 {
00458 // Get the frames to skip.
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 //TRACE("VRender::run 3");
00469 //printf("VRender:run 11 frame_step %d\n", frame_step);
00470                         }
00471                         else
00472                         {
00473 // Frame rendered early or just in time.
00474                                 frame_step = 1;
00475 //TRACE("VRender::run 4");
00476 
00477                                 if(delay_countdown > 0)
00478                                 {
00479 // Maybe just a freak
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 //printf("VRender:run 10 %lld\n", delay_time);
00492                                         }
00493                                         else
00494                                         {
00495 // Came after the earliest sample so keep going
00496                                         }
00497                                 }
00498 
00499 //TRACE("VRender::run 5");
00500 // Flash frame now.
00501                                 flash_output();
00502 //TRACE("VRender::run 6");
00503                         }
00504                 }
00505 
00506 // Trigger audio to start
00507                 if(first_frame)
00508                 {
00509                         renderengine->first_frame_lock->unlock();
00510                         first_frame = 0;
00511                         renderengine->reset_sync_position();
00512                 }
00513 //TRACE("VRender::run 5");
00514 
00515                 session_frame += frame_step;
00516 
00517 // advance position in project
00518                 current_input_length = frame_step;
00519 
00520 
00521 // Subtract frame_step in a loop to allow looped playback to drain
00522                 while(frame_step && current_input_length && !last_playback)
00523                 {
00524 // set last_playback if necessary and trim current_input_length to range
00525                         get_boundaries(current_input_length);
00526 // advance 1 frame
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 // Update tracking.
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 // Calculate the framerate counter
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 // In case we were interrupted before the first loop
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;     // render 1 frame at a time
00592         framerate_counter = 0;
00593         video_out[0] = 0;
00594         render_strategy = -1;
00595 }
00596 
00597 int VRender::init_device_buffers()
00598 {
00599 // allocate output buffer if there is a video device
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 // start reading input and sending to vrenderthread
00616 // use a thread only if there's a video device
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 }

Generated on Sun Jan 8 13:39:02 2006 for Cinelerra-svn by  doxygen 1.4.4