00001 #include "assets.h"
00002 #include "bccapture.h"
00003 #include "bcsignals.h"
00004 #include "canvas.h"
00005 #include "colormodels.h"
00006 #include "edl.h"
00007 #include "edlsession.h"
00008 #include "mwindow.h"
00009 #include "playback3d.h"
00010 #include "playbackconfig.h"
00011 #include "preferences.h"
00012 #include "recordconfig.h"
00013 #include "strategies.inc"
00014 #include "vdevicex11.h"
00015 #include "vframe.h"
00016 #include "videodevice.h"
00017 #include "videowindow.h"
00018 #include "videowindowgui.h"
00019
00020 #include <string.h>
00021 #include <unistd.h>
00022
00023 VDeviceX11::VDeviceX11(VideoDevice *device, Canvas *output)
00024 : VDeviceBase(device)
00025 {
00026 reset_parameters();
00027 this->output = output;
00028 }
00029
00030 VDeviceX11::~VDeviceX11()
00031 {
00032 close_all();
00033 }
00034
00035 int VDeviceX11::reset_parameters()
00036 {
00037 output_frame = 0;
00038 window_id = 0;
00039 bitmap = 0;
00040 bitmap_type = 0;
00041 bitmap_w = 0;
00042 bitmap_h = 0;
00043 output_x1 = 0;
00044 output_y1 = 0;
00045 output_x2 = 0;
00046 output_y2 = 0;
00047 canvas_x1 = 0;
00048 canvas_y1 = 0;
00049 canvas_x2 = 0;
00050 canvas_y2 = 0;
00051 capture_bitmap = 0;
00052 color_model_selected = 0;
00053 is_cleared = 0;
00054 return 0;
00055 }
00056
00057 int VDeviceX11::open_input()
00058 {
00059
00060 capture_bitmap = new BC_Capture(device->in_config->w,
00061 device->in_config->h,
00062 device->in_config->screencapture_display);
00063
00064
00065 return 0;
00066 }
00067
00068 int VDeviceX11::open_output()
00069 {
00070 if(output)
00071 {
00072 output->lock_canvas("VDeviceX11::open_output");
00073 output->get_canvas()->lock_window("VDeviceX11::open_output");
00074 if(!device->single_frame)
00075 output->start_video();
00076 else
00077 output->start_single();
00078 output->get_canvas()->unlock_window();
00079
00080
00081
00082 output->unlock_canvas();
00083 }
00084 return 0;
00085 }
00086
00087
00088 int VDeviceX11::output_visible()
00089 {
00090 if(!output) return 0;
00091
00092 output->lock_canvas("VDeviceX11::output_visible");
00093 if(output->get_canvas()->get_hidden())
00094 {
00095 output->unlock_canvas();
00096 return 0;
00097 }
00098 else
00099 {
00100 output->unlock_canvas();
00101 return 1;
00102 }
00103 }
00104
00105
00106 int VDeviceX11::close_all()
00107 {
00108 if(output)
00109 {
00110 output->lock_canvas("VDeviceX11::close_all 1");
00111 output->get_canvas()->lock_window("VDeviceX11::close_all 1");
00112 }
00113
00114 if(output && output_frame)
00115 {
00116
00117
00118
00119
00120 int use_opengl = device->out_config->driver == PLAYBACK_X11_GL &&
00121 output_frame->get_opengl_state() == VFrame::SCREEN;
00122 int best_color_model = output_frame->get_color_model();
00123
00124
00125 if(use_opengl)
00126 best_color_model = BC_RGB888;
00127
00128 if(output->refresh_frame &&
00129 (output->refresh_frame->get_w() != device->out_w ||
00130 output->refresh_frame->get_h() != device->out_h ||
00131 output->refresh_frame->get_color_model() != best_color_model))
00132 {
00133 delete output->refresh_frame;
00134 output->refresh_frame = 0;
00135 }
00136
00137 if(!output->refresh_frame)
00138 {
00139 output->refresh_frame = new VFrame(0,
00140 device->out_w,
00141 device->out_h,
00142 best_color_model);
00143 }
00144
00145 if(use_opengl)
00146 {
00147 output->get_canvas()->unlock_window();
00148 output->unlock_canvas();
00149
00150 output->mwindow->playback_3d->copy_from(output,
00151 output->refresh_frame,
00152 output_frame,
00153 0);
00154 output->lock_canvas("VDeviceX11::close_all 2");
00155 output->get_canvas()->lock_window("VDeviceX11::close_all 2");
00156 }
00157 else
00158 output->refresh_frame->copy_from(output_frame);
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 if(
00176 device->single_frame)
00177 output->draw_refresh();
00178 }
00179
00180
00181
00182
00183 if(bitmap)
00184 {
00185 delete bitmap;
00186 bitmap = 0;
00187 }
00188
00189 if(output_frame)
00190 {
00191 delete output_frame;
00192 output_frame = 0;
00193 }
00194
00195 if(capture_bitmap) delete capture_bitmap;
00196
00197 if(output)
00198 {
00199
00200
00201 if(!device->single_frame)
00202 {
00203 output->stop_video();
00204 }
00205 else
00206 {
00207 output->stop_single();
00208 }
00209
00210 output->get_canvas()->unlock_window();
00211 output->unlock_canvas();
00212 }
00213
00214
00215 reset_parameters();
00216 return 0;
00217 }
00218
00219 int VDeviceX11::read_buffer(VFrame *frame)
00220 {
00221 capture_bitmap->capture_frame(frame, device->input_x, device->input_y);
00222 return 0;
00223 }
00224
00225
00226 int VDeviceX11::get_best_colormodel(Asset *asset)
00227 {
00228 return BC_RGB888;
00229 }
00230
00231
00232 int VDeviceX11::get_best_colormodel(int colormodel)
00233 {
00234 int result = -1;
00235
00236 if(device->out_config->driver == PLAYBACK_X11_GL)
00237 {
00238 if(colormodel == BC_RGB888 ||
00239 colormodel == BC_RGBA8888 ||
00240 colormodel == BC_YUV888 ||
00241 colormodel == BC_YUVA8888 ||
00242 colormodel == BC_RGB_FLOAT ||
00243 colormodel == BC_RGBA_FLOAT)
00244 {
00245 return colormodel;
00246 }
00247 return BC_RGB888;
00248 }
00249
00250 if(!device->single_frame)
00251 {
00252 switch(colormodel)
00253 {
00254 case BC_YUV420P:
00255 case BC_YUV422P:
00256 case BC_YUV422:
00257 result = colormodel;
00258 break;
00259 }
00260 }
00261
00262
00263 if(device->out_config->driver == PLAYBACK_X11_GL)
00264 {
00265 if(colormodel == BC_RGB_FLOAT ||
00266 colormodel == BC_RGBA_FLOAT)
00267 result = colormodel;
00268 }
00269
00270 if(result < 0)
00271 {
00272 switch(colormodel)
00273 {
00274 case BC_RGB888:
00275 case BC_RGBA8888:
00276 case BC_YUV888:
00277 case BC_YUVA8888:
00278 result = colormodel;
00279 break;
00280
00281 default:
00282 output->lock_canvas("VDeviceX11::get_best_colormodel");
00283 result = output->get_canvas()->get_color_model();
00284 output->unlock_canvas();
00285 break;
00286 }
00287 }
00288
00289 return result;
00290 }
00291
00292
00293 void VDeviceX11::new_output_buffer(VFrame **result, int colormodel)
00294 {
00295
00296 output->lock_canvas("VDeviceX11::new_output_buffer");
00297 output->get_canvas()->lock_window("VDeviceX11::new_output_buffer 1");
00298
00299
00300 int best_colormodel = get_best_colormodel(colormodel);
00301
00302
00303 if(device->out_config->driver == PLAYBACK_X11_GL)
00304 {
00305
00306
00307 if(!output_frame)
00308 {
00309 output_frame = new VFrame(0,
00310 device->out_w,
00311 device->out_h,
00312 colormodel);
00313
00314 }
00315
00316 window_id = output->get_canvas()->get_id();
00317 output_frame->set_opengl_state(VFrame::RAM);
00318 }
00319 else
00320 {
00321
00322 if(bitmap)
00323 {
00324
00325
00326 if(!color_model_selected ||
00327 (!bitmap->hardware_scaling() &&
00328 (bitmap->get_w() != output->get_canvas()->get_w() ||
00329 bitmap->get_h() != output->get_canvas()->get_h())) ||
00330 colormodel != output_frame->get_color_model())
00331 {
00332 int size_change = (bitmap->get_w() != output->get_canvas()->get_w() ||
00333 bitmap->get_h() != output->get_canvas()->get_h());
00334 delete bitmap;
00335 delete output_frame;
00336 bitmap = 0;
00337 output_frame = 0;
00338
00339
00340 if(size_change)
00341 {
00342 output->get_canvas()->set_color(BLACK);
00343 output->get_canvas()->draw_box(0, 0, output->w, output->h);
00344 output->get_canvas()->flash();
00345 }
00346 }
00347 else
00348
00349 if(bitmap_type == BITMAP_PRIMARY)
00350 {
00351
00352 output_frame->set_memory((unsigned char*)bitmap->get_data() ,
00353 bitmap->get_y_offset(),
00354 bitmap->get_u_offset(),
00355 bitmap->get_v_offset());
00356 }
00357 }
00358
00359
00360 if(!bitmap)
00361 {
00362
00363 switch(best_colormodel)
00364 {
00365 case BC_YUV420P:
00366 if(device->out_config->driver == PLAYBACK_X11_XV &&
00367 output->get_canvas()->accel_available(best_colormodel, 0) &&
00368 !output->use_scrollbars)
00369 {
00370 bitmap = new BC_Bitmap(output->get_canvas(),
00371 device->out_w,
00372 device->out_h,
00373 best_colormodel,
00374 1);
00375 output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(),
00376 bitmap->get_y_offset(),
00377 bitmap->get_u_offset(),
00378 bitmap->get_v_offset(),
00379 device->out_w,
00380 device->out_h,
00381 best_colormodel);
00382 bitmap_type = BITMAP_PRIMARY;
00383 }
00384 break;
00385
00386 case BC_YUV422P:
00387 if(device->out_config->driver == PLAYBACK_X11_XV &&
00388 output->get_canvas()->accel_available(best_colormodel, 0) &&
00389 !output->use_scrollbars)
00390 {
00391 bitmap = new BC_Bitmap(output->get_canvas(),
00392 device->out_w,
00393 device->out_h,
00394 best_colormodel,
00395 1);
00396 output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(),
00397 bitmap->get_y_offset(),
00398 bitmap->get_u_offset(),
00399 bitmap->get_v_offset(),
00400 device->out_w,
00401 device->out_h,
00402 best_colormodel);
00403 bitmap_type = BITMAP_PRIMARY;
00404 }
00405 else
00406 if(device->out_config->driver == PLAYBACK_X11_XV &&
00407 output->get_canvas()->accel_available(BC_YUV422, 0))
00408 {
00409 bitmap = new BC_Bitmap(output->get_canvas(),
00410 device->out_w,
00411 device->out_h,
00412 BC_YUV422,
00413 1);
00414 bitmap_type = BITMAP_TEMP;
00415 }
00416 break;
00417
00418 case BC_YUV422:
00419 if(device->out_config->driver == PLAYBACK_X11_XV &&
00420 output->get_canvas()->accel_available(best_colormodel, 0) &&
00421 !output->use_scrollbars)
00422 {
00423 bitmap = new BC_Bitmap(output->get_canvas(),
00424 device->out_w,
00425 device->out_h,
00426 best_colormodel,
00427 1);
00428 output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(),
00429 bitmap->get_y_offset(),
00430 bitmap->get_u_offset(),
00431 bitmap->get_v_offset(),
00432 device->out_w,
00433 device->out_h,
00434 best_colormodel);
00435 bitmap_type = BITMAP_PRIMARY;
00436 }
00437 else
00438 if(device->out_config->driver == PLAYBACK_X11_XV &&
00439 output->get_canvas()->accel_available(BC_YUV422P, 0))
00440 {
00441 bitmap = new BC_Bitmap(output->get_canvas(),
00442 device->out_w,
00443 device->out_h,
00444 BC_YUV422P,
00445 1);
00446 bitmap_type = BITMAP_TEMP;
00447 }
00448 break;
00449 }
00450
00451
00452 if(!bitmap)
00453 {
00454 best_colormodel = output->get_canvas()->get_color_model();
00455 bitmap = new BC_Bitmap(output->get_canvas(),
00456 output->get_canvas()->get_w(),
00457 output->get_canvas()->get_h(),
00458 best_colormodel,
00459 1);
00460 bitmap_type = BITMAP_TEMP;
00461 }
00462
00463 if(bitmap_type == BITMAP_TEMP)
00464 {
00465
00466 output_frame = new VFrame(0,
00467 device->out_w,
00468 device->out_h,
00469 colormodel);
00470
00471
00472
00473
00474
00475
00476
00477 bitmap_type = BITMAP_TEMP;
00478 }
00479 color_model_selected = 1;
00480 }
00481
00482
00483 if(bitmap_type == BITMAP_PRIMARY)
00484 {
00485
00486 output_frame->set_shm_offset(bitmap->get_shm_offset());
00487 }
00488 else
00489 if(bitmap_type == BITMAP_TEMP)
00490 {
00491 output_frame->set_shm_offset(0);
00492 }
00493 }
00494
00495
00496 *result = output_frame;
00497
00498 output->get_canvas()->unlock_window();
00499 output->unlock_canvas();
00500
00501 }
00502
00503
00504 int VDeviceX11::start_playback()
00505 {
00506
00507 if(!device->single_frame)
00508 output->start_video();
00509 return 0;
00510 }
00511
00512 int VDeviceX11::stop_playback()
00513 {
00514 if(!device->single_frame)
00515 output->stop_video();
00516
00517
00518 return 0;
00519 }
00520
00521 int VDeviceX11::write_buffer(VFrame *output_channels, EDL *edl)
00522 {
00523
00524
00525 if (device->single_frame)
00526 return 0;
00527
00528 int i = 0;
00529 output->lock_canvas("VDeviceX11::write_buffer");
00530 output->get_canvas()->lock_window("VDeviceX11::write_buffer 1");
00531
00532
00533
00534 output->get_transfers(edl,
00535 output_x1,
00536 output_y1,
00537 output_x2,
00538 output_y2,
00539 canvas_x1,
00540 canvas_y1,
00541 canvas_x2,
00542 canvas_y2,
00543
00544 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_w() : -1,
00545 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_h() : -1);
00546
00547
00548
00549 if(bitmap_type == BITMAP_TEMP)
00550 {
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 if(bitmap->hardware_scaling())
00568 {
00569 cmodel_transfer(bitmap->get_row_pointers(),
00570 output_channels->get_rows(),
00571 0,
00572 0,
00573 0,
00574 output_channels->get_y(),
00575 output_channels->get_u(),
00576 output_channels->get_v(),
00577 0,
00578 0,
00579 output_channels->get_w(),
00580 output_channels->get_h(),
00581 0,
00582 0,
00583 bitmap->get_w(),
00584 bitmap->get_h(),
00585 output_channels->get_color_model(),
00586 bitmap->get_color_model(),
00587 0,
00588 output_channels->get_w(),
00589 bitmap->get_w());
00590 }
00591 else
00592 {
00593 cmodel_transfer(bitmap->get_row_pointers(),
00594 output_channels->get_rows(),
00595 0,
00596 0,
00597 0,
00598 output_channels->get_y(),
00599 output_channels->get_u(),
00600 output_channels->get_v(),
00601 (int)output_x1,
00602 (int)output_y1,
00603 (int)(output_x2 - output_x1),
00604 (int)(output_y2 - output_y1),
00605 0,
00606 0,
00607 (int)(canvas_x2 - canvas_x1),
00608 (int)(canvas_y2 - canvas_y1),
00609 output_channels->get_color_model(),
00610 bitmap->get_color_model(),
00611 0,
00612 output_channels->get_w(),
00613 bitmap->get_w());
00614 }
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 if(device->out_config->driver == PLAYBACK_X11_GL)
00638 {
00639
00640 if(output->get_canvas()->get_video_on())
00641 {
00642
00643 output->get_canvas()->unlock_window();
00644 output->unlock_canvas();
00645 output->mwindow->playback_3d->write_buffer(output,
00646 output_frame,
00647 output_x1,
00648 output_y1,
00649 output_x2,
00650 output_y2,
00651 canvas_x1,
00652 canvas_y1,
00653 canvas_x2,
00654 canvas_y2,
00655 is_cleared);
00656 is_cleared = 0;
00657 output->lock_canvas("VDeviceX11::write_buffer 2");
00658 output->get_canvas()->lock_window("VDeviceX11::write_buffer 2");
00659 }
00660 }
00661 else
00662 if(bitmap->hardware_scaling())
00663 {
00664 output->get_canvas()->draw_bitmap(bitmap,
00665 !device->single_frame,
00666 (int)canvas_x1,
00667 (int)canvas_y1,
00668 (int)(canvas_x2 - canvas_x1),
00669 (int)(canvas_y2 - canvas_y1),
00670 (int)output_x1,
00671 (int)output_y1,
00672 (int)(output_x2 - output_x1),
00673 (int)(output_y2 - output_y1),
00674 0);
00675 }
00676 else
00677 {
00678 output->get_canvas()->draw_bitmap(bitmap,
00679 !device->single_frame,
00680 (int)canvas_x1,
00681 (int)canvas_y1,
00682 (int)(canvas_x2 - canvas_x1),
00683 (int)(canvas_y2 - canvas_y1),
00684 0,
00685 0,
00686 (int)(canvas_x2 - canvas_x1),
00687 (int)(canvas_y2 - canvas_y1),
00688 0);
00689 }
00690
00691
00692 output->get_canvas()->unlock_window();
00693 output->unlock_canvas();
00694 return 0;
00695 }
00696
00697
00698 void VDeviceX11::clear_output()
00699 {
00700 is_cleared = 1;
00701
00702 output->mwindow->playback_3d->clear_output(output,
00703 output->get_canvas()->get_video_on() ? 0 : output_frame);
00704
00705 }
00706
00707
00708 void VDeviceX11::clear_input(VFrame *frame)
00709 {
00710 this->output->mwindow->playback_3d->clear_input(this->output, frame);
00711 }
00712
00713 void VDeviceX11::do_camera(VFrame *output,
00714 VFrame *input,
00715 float in_x1,
00716 float in_y1,
00717 float in_x2,
00718 float in_y2,
00719 float out_x1,
00720 float out_y1,
00721 float out_x2,
00722 float out_y2)
00723 {
00724 this->output->mwindow->playback_3d->do_camera(this->output,
00725 output,
00726 input,
00727 in_x1,
00728 in_y1,
00729 in_x2,
00730 in_y2,
00731 out_x1,
00732 out_y1,
00733 out_x2,
00734 out_y2);
00735 }
00736
00737
00738 void VDeviceX11::do_fade(VFrame *output_temp, float fade)
00739 {
00740 this->output->mwindow->playback_3d->do_fade(this->output, output_temp, fade);
00741 }
00742
00743 void VDeviceX11::do_mask(VFrame *output_temp,
00744 int64_t start_position_project,
00745 MaskAutos *keyframe_set,
00746 MaskAuto *keyframe,
00747 MaskAuto *default_auto)
00748 {
00749 this->output->mwindow->playback_3d->do_mask(output,
00750 output_temp,
00751 start_position_project,
00752 keyframe_set,
00753 keyframe,
00754 default_auto);
00755 }
00756
00757 void VDeviceX11::overlay(VFrame *output_frame,
00758 VFrame *input,
00759
00760 float in_x1,
00761 float in_y1,
00762 float in_x2,
00763 float in_y2,
00764 float out_x1,
00765 float out_y1,
00766 float out_x2,
00767 float out_y2,
00768 float alpha,
00769 int mode,
00770 EDL *edl)
00771 {
00772 int interpolation_type = edl->session->interpolation_type;
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 output->lock_canvas("VDeviceX11::overlay");
00787 output->get_canvas()->lock_window("VDeviceX11::overlay");
00788
00789
00790 output->get_transfers(edl,
00791 output_x1,
00792 output_y1,
00793 output_x2,
00794 output_y2,
00795 canvas_x1,
00796 canvas_y1,
00797 canvas_x2,
00798 canvas_y2,
00799 -1,
00800 -1);
00801
00802 output->get_canvas()->unlock_window();
00803 output->unlock_canvas();
00804
00805
00806
00807 if(device->single_frame)
00808 {
00809 output->mwindow->playback_3d->overlay(output,
00810 input,
00811 in_x1,
00812 in_y1,
00813 in_x2,
00814 in_y2,
00815 out_x1,
00816 out_y1,
00817 out_x2,
00818 out_y2,
00819 alpha,
00820 mode,
00821 interpolation_type,
00822 output_frame);
00823
00824
00825
00826
00827
00828 }
00829 else
00830 {
00831
00832
00833 float track_xscale = (out_x2 - out_x1) / (in_x2 - in_x1);
00834 float track_yscale = (out_y2 - out_y1) / (in_y2 - in_y1);
00835 float canvas_xscale = (float)(canvas_x2 - canvas_x1) / (output_x2 - output_x1);
00836 float canvas_yscale = (float)(canvas_y2 - canvas_y1) / (output_y2 - output_y1);
00837
00838
00839
00840 float track_x1 = (float)(output_x1 - out_x1) / track_xscale + in_x1;
00841 float track_y1 = (float)(output_y1 - out_y1) / track_yscale + in_y1;
00842 float track_x2 = (float)(output_x2 - out_x2) / track_xscale + in_x2;
00843 float track_y2 = (float)(output_y2 - out_y2) / track_yscale + in_y2;
00844
00845
00846 if(track_x1 < 0)
00847 {
00848 float difference = -track_x1;
00849 track_x1 += difference;
00850 canvas_x1 += difference * track_xscale * canvas_xscale;
00851 }
00852 if(track_y1 < 0)
00853 {
00854 float difference = -track_y1;
00855 track_y1 += difference;
00856 canvas_y1 += difference * track_yscale * canvas_yscale;
00857 }
00858
00859 if(track_x2 > input->get_w())
00860 {
00861 float difference = track_x2 - input->get_w();
00862 track_x2 -= difference;
00863 canvas_x2 -= difference * track_xscale * canvas_xscale;
00864 }
00865 if(track_y2 > input->get_h())
00866 {
00867 float difference = track_y2 - input->get_h();
00868 track_y2 -= difference;
00869 canvas_y2 -= difference * track_yscale * canvas_yscale;
00870 }
00871
00872
00873
00874
00875
00876
00877 if(track_x2 > track_x1 &&
00878 track_y2 > track_y1 &&
00879 canvas_x2 > canvas_x1 &&
00880 canvas_y2 > canvas_y1)
00881 {
00882 output->mwindow->playback_3d->overlay(output,
00883 input,
00884 track_x1,
00885 track_y1,
00886 track_x2,
00887 track_y2,
00888 canvas_x1,
00889 canvas_y1,
00890 canvas_x2,
00891 canvas_y2,
00892 alpha,
00893 mode,
00894 interpolation_type);
00895 }
00896 }
00897 }
00898
00899 void VDeviceX11::run_plugin(PluginClient *client)
00900 {
00901 output->mwindow->playback_3d->run_plugin(output, client);
00902 }
00903
00904 void VDeviceX11::copy_frame(VFrame *dst, VFrame *src)
00905 {
00906 output->mwindow->playback_3d->copy_from(output, dst, src, 1);
00907 }
00908