5 #include "colormodels.h"
7 #include "edlsession.h"
9 #include "playback3d.h"
10 #include "playbackconfig.h"
11 #include "preferences.h"
12 #include "recordconfig.h"
13 #include "strategies.inc"
14 #include "vdevicex11.h"
16 #include "videodevice.h"
17 #include "videowindow.h"
18 #include "videowindowgui.h"
23 VDeviceX11::VDeviceX11(VideoDevice *device, Canvas *output)
27 this->output = output;
30 VDeviceX11::~VDeviceX11()
35 int VDeviceX11::reset_parameters()
52 color_model_selected = 0;
57 int VDeviceX11::open_input()
59 //printf("VDeviceX11::open_input 1\n");
60 capture_bitmap = new BC_Capture(device->in_config->w,
62 device->in_config->screencapture_display);
63 //printf("VDeviceX11::open_input 2\n");
68 int VDeviceX11::open_output()
72 output->lock_canvas("VDeviceX11::open_output");
73 output->get_canvas()->lock_window("VDeviceX11::open_output");
74 if(!device->single_frame)
75 output->start_video();
77 output->start_single();
78 output->get_canvas()->unlock_window();
80 // Enable opengl in the first routine that needs it, to reduce the complexity.
82 output->unlock_canvas();
88 int VDeviceX11::output_visible()
92 output->lock_canvas("VDeviceX11::output_visible");
93 if(output->get_canvas()->get_hidden())
95 output->unlock_canvas();
100 output->unlock_canvas();
106 int VDeviceX11::close_all()
110 output->lock_canvas("VDeviceX11::close_all 1");
111 output->get_canvas()->lock_window("VDeviceX11::close_all 1");
114 if(output && output_frame)
116 // Copy our output frame buffer to the canvas's permanent frame buffer.
117 // They must be different buffers because the output frame is being written
118 // while the user is redrawing the canvas frame buffer over and over.
120 int use_opengl = device->out_config->driver == PLAYBACK_X11_GL &&
121 output_frame->get_opengl_state() == VFrame::SCREEN;
122 int best_color_model = output_frame->get_color_model();
124 // OpenGL does YUV->RGB in the compositing step
126 best_color_model = BC_RGB888;
128 if(output->refresh_frame &&
129 (output->refresh_frame->get_w() != device->out_w ||
130 output->refresh_frame->get_h() != device->out_h ||
131 output->refresh_frame->get_color_model() != best_color_model))
133 delete output->refresh_frame;
134 output->refresh_frame = 0;
137 if(!output->refresh_frame)
139 output->refresh_frame = new VFrame(0,
147 output->get_canvas()->unlock_window();
148 output->unlock_canvas();
150 output->mwindow->playback_3d->copy_from(output,
151 output->refresh_frame,
154 output->lock_canvas("VDeviceX11::close_all 2");
155 output->get_canvas()->lock_window("VDeviceX11::close_all 2");
158 output->refresh_frame->copy_from(output_frame);
160 // // Update the status bug
161 // if(!device->single_frame)
163 // output->stop_video();
167 // output->stop_single();
170 // Draw the first refresh with new frame.
171 // Doesn't work if video and openGL because OpenGL doesn't have
172 // the output buffer for video.
173 // Not necessary for any case if we mandate a frame advance after
175 if(/* device->out_config->driver != PLAYBACK_X11_GL ||
176 */ device->single_frame)
177 output->draw_refresh();
195 if(capture_bitmap) delete capture_bitmap;
200 // Update the status bug
201 if(!device->single_frame)
203 output->stop_video();
207 output->stop_single();
210 output->get_canvas()->unlock_window();
211 output->unlock_canvas();
219 int VDeviceX11::read_buffer(VFrame *frame)
221 capture_bitmap->capture_frame(frame, device->input_x, device->input_y);
226 int VDeviceX11::get_best_colormodel(Asset_GC asset)
232 int VDeviceX11::get_best_colormodel(int colormodel)
236 if(device->out_config->driver == PLAYBACK_X11_GL)
238 if(colormodel == BC_RGB888 ||
239 colormodel == BC_RGBA8888 ||
240 colormodel == BC_YUV888 ||
241 colormodel == BC_YUVA8888 ||
242 colormodel == BC_RGB_FLOAT ||
243 colormodel == BC_RGBA_FLOAT)
250 if(!device->single_frame)
262 // 2 more colormodels are supported by OpenGL
263 if(device->out_config->driver == PLAYBACK_X11_GL)
265 if(colormodel == BC_RGB_FLOAT ||
266 colormodel == BC_RGBA_FLOAT)
282 output->lock_canvas("VDeviceX11::get_best_colormodel");
283 result = output->get_canvas()->get_color_model();
284 output->unlock_canvas();
293 void VDeviceX11::new_output_buffer(VFrame **result, int colormodel)
295 //printf("VDeviceX11::new_output_buffer 1\n");
296 output->lock_canvas("VDeviceX11::new_output_buffer");
297 output->get_canvas()->lock_window("VDeviceX11::new_output_buffer 1");
299 // Get the best colormodel the display can handle.
300 int best_colormodel = get_best_colormodel(colormodel);
302 // Only create OpenGL Pbuffer and texture.
303 if(device->out_config->driver == PLAYBACK_X11_GL)
305 // Create bitmap for initial load into texture.
306 // Not necessary to do through Playback3D.....yet
309 output_frame = new VFrame(0,
313 //BUFFER2(output_frame->get_rows()[0], "VDeviceX11::new_output_buffer 1");
316 window_id = output->get_canvas()->get_id();
317 output_frame->set_opengl_state(VFrame::RAM);
321 // Conform existing bitmap to new colormodel and output size
324 // Restart if output size changed or output colormodel changed.
325 // May have to recreate if transferring between windowed and fullscreen.
326 if(!color_model_selected ||
327 (!bitmap->hardware_scaling() &&
328 (bitmap->get_w() != output->get_canvas()->get_w() ||
329 bitmap->get_h() != output->get_canvas()->get_h())) ||
330 colormodel != output_frame->get_color_model())
332 int size_change = (bitmap->get_w() != output->get_canvas()->get_w() ||
333 bitmap->get_h() != output->get_canvas()->get_h());
339 // Blank only if size changed
342 output->get_canvas()->set_color(BLACK);
343 output->get_canvas()->draw_box(0, 0, output->w, output->h);
344 output->get_canvas()->flash();
348 // Update the ring buffer
349 if(bitmap_type == BITMAP_PRIMARY)
352 output_frame->set_memory((unsigned char*)bitmap->get_data() /* + bitmap->get_shm_offset() */,
353 bitmap->get_y_offset(),
354 bitmap->get_u_offset(),
355 bitmap->get_v_offset());
362 // Try hardware accelerated
363 switch(best_colormodel)
366 if(device->out_config->driver == PLAYBACK_X11_XV &&
367 output->get_canvas()->accel_available(best_colormodel, 0) &&
368 !output->use_scrollbars)
370 bitmap = new BC_Bitmap(output->get_canvas(),
375 output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(),
376 bitmap->get_y_offset(),
377 bitmap->get_u_offset(),
378 bitmap->get_v_offset(),
382 bitmap_type = BITMAP_PRIMARY;
387 if(device->out_config->driver == PLAYBACK_X11_XV &&
388 output->get_canvas()->accel_available(best_colormodel, 0) &&
389 !output->use_scrollbars)
391 bitmap = new BC_Bitmap(output->get_canvas(),
396 output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(),
397 bitmap->get_y_offset(),
398 bitmap->get_u_offset(),
399 bitmap->get_v_offset(),
403 bitmap_type = BITMAP_PRIMARY;
406 if(device->out_config->driver == PLAYBACK_X11_XV &&
407 output->get_canvas()->accel_available(BC_YUV422, 0))
409 bitmap = new BC_Bitmap(output->get_canvas(),
414 bitmap_type = BITMAP_TEMP;
419 if(device->out_config->driver == PLAYBACK_X11_XV &&
420 output->get_canvas()->accel_available(best_colormodel, 0) &&
421 !output->use_scrollbars)
423 bitmap = new BC_Bitmap(output->get_canvas(),
428 output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(),
429 bitmap->get_y_offset(),
430 bitmap->get_u_offset(),
431 bitmap->get_v_offset(),
435 bitmap_type = BITMAP_PRIMARY;
438 if(device->out_config->driver == PLAYBACK_X11_XV &&
439 output->get_canvas()->accel_available(BC_YUV422P, 0))
441 bitmap = new BC_Bitmap(output->get_canvas(),
446 bitmap_type = BITMAP_TEMP;
451 // Try default colormodel
454 best_colormodel = output->get_canvas()->get_color_model();
455 bitmap = new BC_Bitmap(output->get_canvas(),
456 output->get_canvas()->get_w(),
457 output->get_canvas()->get_h(),
460 bitmap_type = BITMAP_TEMP;
463 if(bitmap_type == BITMAP_TEMP)
465 // Intermediate frame
466 output_frame = new VFrame(0,
470 // printf("VDeviceX11::new_outout_buffer %p %d %d %d %p\n",
475 // output_frame->get_rows());
476 //BUFFER2(output_frame->get_rows()[0], "VDeviceX11::new_output_buffer 2");
477 bitmap_type = BITMAP_TEMP;
479 color_model_selected = 1;
483 if(bitmap_type == BITMAP_PRIMARY)
485 // Only useful if the primary is RGB888 which XFree86 never uses.
486 output_frame->set_shm_offset(bitmap->get_shm_offset());
489 if(bitmap_type == BITMAP_TEMP)
491 output_frame->set_shm_offset(0);
496 *result = output_frame;
498 output->get_canvas()->unlock_window();
499 output->unlock_canvas();
500 //printf("VDeviceX11::new_output_buffer 10\n");
504 int VDeviceX11::start_playback()
506 // Record window is initialized when its monitor starts.
507 if(!device->single_frame)
508 output->start_video();
512 int VDeviceX11::stop_playback()
514 if(!device->single_frame)
515 output->stop_video();
516 // Record window goes back to monitoring
517 // get the last frame played and store it in the video_out
521 int VDeviceX11::write_buffer(VFrame *output_channels, EDL *edl)
523 // The reason for not drawing single frame is that it is _always_ drawn
524 // when drawing draw_refresh in cwindowgui and vwindowgui
525 if (device->single_frame)
529 output->lock_canvas("VDeviceX11::write_buffer");
530 output->get_canvas()->lock_window("VDeviceX11::write_buffer 1");
533 //printf("VDeviceX11::write_buffer %d\n", output->get_canvas()->get_video_on());
534 output->get_transfers(edl,
543 // Canvas may be a different size than the temporary bitmap for pure software
544 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_w() : -1,
545 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_h() : -1);
548 // Convert colormodel
549 if(bitmap_type == BITMAP_TEMP)
551 // printf("VDeviceX11::write_buffer 1 %d %d, %d %d %d %d -> %d %d %d %d\n",
564 //printf("VDeviceX11::write_buffer 2\n");
567 if(bitmap->hardware_scaling())
569 cmodel_transfer(bitmap->get_row_pointers(),
570 output_channels->get_rows(),
574 output_channels->get_y(),
575 output_channels->get_u(),
576 output_channels->get_v(),
579 output_channels->get_w(),
580 output_channels->get_h(),
585 output_channels->get_color_model(),
586 bitmap->get_color_model(),
588 output_channels->get_w(),
593 cmodel_transfer(bitmap->get_row_pointers(),
594 output_channels->get_rows(),
598 output_channels->get_y(),
599 output_channels->get_u(),
600 output_channels->get_v(),
603 (int)(output_x2 - output_x1),
604 (int)(output_y2 - output_y1),
607 (int)(canvas_x2 - canvas_x1),
608 (int)(canvas_y2 - canvas_y1),
609 output_channels->get_color_model(),
610 bitmap->get_color_model(),
612 output_channels->get_w(),
617 //printf("VDeviceX11::write_buffer 4 %p\n", bitmap);
618 //for(i = 0; i < 1000; i += 4) bitmap->get_data()[i] = 128;
619 //printf("VDeviceX11::write_buffer 2 %d %d %d\n", bitmap_type,
620 // bitmap->get_color_model(),
621 // output->get_color_model());fflush(stdout);
622 // printf("VDeviceX11::write_buffer 2 %d %d, %f %f %f %f -> %f %f %f %f\n",
636 // Cause X server to display it
637 if(device->out_config->driver == PLAYBACK_X11_GL)
639 // Output is drawn in close_all if no video.
640 if(output->get_canvas()->get_video_on())
642 // Draw output frame directly. Not used for compositing.
643 output->get_canvas()->unlock_window();
644 output->unlock_canvas();
645 output->mwindow->playback_3d->write_buffer(output,
657 output->lock_canvas("VDeviceX11::write_buffer 2");
658 output->get_canvas()->lock_window("VDeviceX11::write_buffer 2");
662 if(bitmap->hardware_scaling())
664 output->get_canvas()->draw_bitmap(bitmap,
665 !device->single_frame,
668 (int)(canvas_x2 - canvas_x1),
669 (int)(canvas_y2 - canvas_y1),
672 (int)(output_x2 - output_x1),
673 (int)(output_y2 - output_y1),
678 output->get_canvas()->draw_bitmap(bitmap,
679 !device->single_frame,
682 (int)(canvas_x2 - canvas_x1),
683 (int)(canvas_y2 - canvas_y1),
686 (int)(canvas_x2 - canvas_x1),
687 (int)(canvas_y2 - canvas_y1),
692 output->get_canvas()->unlock_window();
693 output->unlock_canvas();
698 void VDeviceX11::clear_output()
702 output->mwindow->playback_3d->clear_output(output,
703 output->get_canvas()->get_video_on() ? 0 : output_frame);
708 void VDeviceX11::clear_input(VFrame *frame)
710 this->output->mwindow->playback_3d->clear_input(this->output, frame);
713 void VDeviceX11::do_camera(VFrame *output,
724 this->output->mwindow->playback_3d->do_camera(this->output,
738 void VDeviceX11::do_fade(VFrame *output_temp, float fade)
740 this->output->mwindow->playback_3d->do_fade(this->output, output_temp, fade);
743 void VDeviceX11::do_mask(VFrame *output_temp,
744 int64_t start_position_project,
745 MaskAutos *keyframe_set,
747 MaskAuto *default_auto)
749 this->output->mwindow->playback_3d->do_mask(output,
751 start_position_project,
757 void VDeviceX11::overlay(VFrame *output_frame,
759 // This is the transfer from track to output frame
768 float alpha, // 0 - 1
772 int interpolation_type = edl->session->interpolation_type;
774 // printf("VDeviceX11::overlay 1:\n"
775 // "in_x1=%f in_y1=%f in_x2=%f in_y2=%f\n"
776 // "out_x1=%f out_y1=%f out_x2=%f out_y2=%f\n",
785 // Convert node coords to canvas coords in here
786 output->lock_canvas("VDeviceX11::overlay");
787 output->get_canvas()->lock_window("VDeviceX11::overlay");
789 // This is the transfer from output frame to canvas
790 output->get_transfers(edl,
802 output->get_canvas()->unlock_window();
803 output->unlock_canvas();
806 // If single frame playback, use full sized PBuffer as output.
807 if(device->single_frame)
809 output->mwindow->playback_3d->overlay(output,
823 // printf("VDeviceX11::overlay 1 %p %d %d %d\n",
825 // output_frame->get_w(),
826 // output_frame->get_h(),
827 // output_frame->get_opengl_state());
832 // Get transfer from track to canvas
833 float track_xscale = (out_x2 - out_x1) / (in_x2 - in_x1);
834 float track_yscale = (out_y2 - out_y1) / (in_y2 - in_y1);
835 float canvas_xscale = (float)(canvas_x2 - canvas_x1) / (output_x2 - output_x1);
836 float canvas_yscale = (float)(canvas_y2 - canvas_y1) / (output_y2 - output_y1);
839 // Get coordinates of canvas relative to track frame
840 float track_x1 = (float)(output_x1 - out_x1) / track_xscale + in_x1;
841 float track_y1 = (float)(output_y1 - out_y1) / track_yscale + in_y1;
842 float track_x2 = (float)(output_x2 - out_x2) / track_xscale + in_x2;
843 float track_y2 = (float)(output_y2 - out_y2) / track_yscale + in_y2;
845 // Clamp canvas coords to track boundary
848 float difference = -track_x1;
849 track_x1 += difference;
850 canvas_x1 += difference * track_xscale * canvas_xscale;
854 float difference = -track_y1;
855 track_y1 += difference;
856 canvas_y1 += difference * track_yscale * canvas_yscale;
859 if(track_x2 > input->get_w())
861 float difference = track_x2 - input->get_w();
862 track_x2 -= difference;
863 canvas_x2 -= difference * track_xscale * canvas_xscale;
865 if(track_y2 > input->get_h())
867 float difference = track_y2 - input->get_h();
868 track_y2 -= difference;
869 canvas_y2 -= difference * track_yscale * canvas_yscale;
876 // Overlay directly from track buffer to canvas, skipping output buffer
877 if(track_x2 > track_x1 &&
878 track_y2 > track_y1 &&
879 canvas_x2 > canvas_x1 &&
880 canvas_y2 > canvas_y1)
882 output->mwindow->playback_3d->overlay(output,
899 void VDeviceX11::run_plugin(PluginClient *client)
901 output->mwindow->playback_3d->run_plugin(output, client);
904 void VDeviceX11::copy_frame(VFrame *dst, VFrame *src)
906 output->mwindow->playback_3d->copy_from(output, dst, src, 1);
912 // c-file-style: "linux"