r665: Merged the official release 2.0.
[cinelerra_cv.git] / cinelerra / vdevicex11.C
blobd2a7d33bb25abb25ba97df2de5a04a560b141b90
1 #include "assets.h"
2 #include "bccapture.h"
3 #include "bcsignals.h"
4 #include "canvas.h"
5 #include "colormodels.h"
6 #include "mwindow.h"
7 #include "playbackconfig.h"
8 #include "preferences.h"
9 #include "recordconfig.h"
10 #include "strategies.inc"
11 #include "vdevicex11.h"
12 #include "vframe.h"
13 #include "videodevice.h"
14 #include "videowindow.h"
15 #include "videowindowgui.h"
17 #include <string.h>
18 #include <unistd.h>
20 VDeviceX11::VDeviceX11(VideoDevice *device, Canvas *output)
21  : VDeviceBase(device)
23         reset_parameters();
24         this->output = output;
27 VDeviceX11::~VDeviceX11()
29         close_all();
32 int VDeviceX11::reset_parameters()
34         output_frame = 0;
35         bitmap = 0;
36         bitmap_w = 0;
37         bitmap_h = 0;
38         output = 0;
39         in_x = 0;
40         in_y = 0;
41         in_w = 0;
42         in_h = 0;
43         out_x = 0;
44         out_y = 0;
45         out_w = 0;
46         out_h = 0;
47         capture_bitmap = 0;
48         color_model_selected = 0;
49         return 0;
52 int VDeviceX11::open_input()
54 //printf("VDeviceX11::open_input 1\n");
55         capture_bitmap = new BC_Capture(device->in_config->w, 
56                 device->in_config->h,
57                 device->in_config->screencapture_display);
58 //printf("VDeviceX11::open_input 2\n");
59         
60         return 0;
63 int VDeviceX11::open_output()
65         if(output)
66         {
67                 output->canvas->lock_window("VDeviceX11::open_output");
68                 if(!device->single_frame)
69                         output->start_video();
70                 else
71                         output->start_single();
72                 output->canvas->unlock_window();
73         }
74         return 0;
78 int VDeviceX11::output_visible()
80         if(!output || output->canvas->get_hidden()) 
81                 return 0; 
82         else 
83                 return 1;
87 int VDeviceX11::close_all()
89         if(output)
90         {
91                 output->canvas->lock_window("VDeviceX11::close_all");
92         }
94         if(output && output_frame)
95         {
96 // We need to copy when the memory is shared, which is when bimap_type is primary
97                 if (bitmap && bitmap_type == BITMAP_PRIMARY)
98                 {
99                         if(output->refresh_frame &&
100                                 (output->refresh_frame->get_w() != device->out_w ||
101                                 output->refresh_frame->get_h() != device->out_h ||
102                                 output->refresh_frame->get_color_model() != output_frame->get_color_model()))
103                         {
104                                 delete output->refresh_frame;
105                                 output->refresh_frame = 0;
106                         }
108                         if(!output->refresh_frame)
109                         {
110                                 output->refresh_frame = new VFrame(0,
111                                         device->out_w,
112                                         device->out_h,
113                                         output_frame->get_color_model());
114                         }
116                         output->refresh_frame->copy_from(output_frame);
117                 }
118                 else 
119                 {
120                         if(output->refresh_frame)
121                                 delete output->refresh_frame;
123                         output->refresh_frame = output_frame;
124                         output_frame = 0;
125                 }
127                 if(!device->single_frame)
128                         output->stop_video();
129                 else
130                         output->stop_single();
131                 output->draw_refresh();
134         } else
135         {
136                 if(bitmap)
137                         delete output_frame;
138         }
139         if(bitmap)
140         {
141                 delete bitmap;
142                 bitmap = 0;
143         }
145         if(capture_bitmap) delete capture_bitmap;
147         if(output)
148         {
149                 output->canvas->unlock_window();
150         }
153         reset_parameters();
154         return 0;
157 int VDeviceX11::read_buffer(VFrame *frame)
159         capture_bitmap->capture_frame(frame, device->input_x, device->input_y);
160         return 0;
164 int VDeviceX11::get_best_colormodel(Asset *asset)
166         return BC_RGB888;
170 int VDeviceX11::get_best_colormodel(int colormodel)
172         int result = -1;
173         if(!device->single_frame)
174         {
175                 switch(colormodel)
176                 {
177                         case BC_YUV420P:
178                         case BC_YUV422P:
179                         case BC_YUV422:
180                                 result = colormodel;
181                                 break;
182                 }
183         }
185         if(result < 0)
186         {
187                 switch(colormodel)
188                 {
189                         case BC_RGB888:
190                         case BC_RGBA8888:
191                         case BC_RGB161616:
192                         case BC_RGBA16161616:
193                         case BC_YUV888:
194                         case BC_YUVA8888:
195                         case BC_YUV161616:
196                         case BC_YUVA16161616:
197                                 result = colormodel;
198                                 break;
200                         default:
201                                 result = output->canvas->get_color_model();
202                                 break;
203                 }
204         }
206 //printf("VDeviceX11::get_best_colormodel %d %d %d\n", device->single_frame, colormodel, result);
207         return result;
211 void VDeviceX11::new_output_buffer(VFrame **output_channels, int colormodel)
213 //TRACE("VDeviceX11::new_output_buffer 1");
214         
215         output->canvas->lock_window("VDeviceX11::new_output_buffer");
217         for(int i = 0; i < MAX_CHANNELS; i++)
218                 output_channels[i] = 0;
220 // Get the best colormodel the display can handle.
221         int best_colormodel = get_best_colormodel(colormodel);
223 // Conform existing bitmap to new colormodel and output size
224         if(bitmap)
225         {
226 // Restart if output size changed or output colormodel changed
227                 if(!color_model_selected ||
228                         (!bitmap->hardware_scaling() && 
229                                 (bitmap->get_w() != output->canvas->get_w() ||
230                                 bitmap->get_h() != output->canvas->get_h())) ||
231                         colormodel != output_frame->get_color_model())
232                 {
233                         int size_change = (bitmap->get_w() != output->canvas->get_w() ||
234                                 bitmap->get_h() != output->canvas->get_h());
235                         delete bitmap;
236                         delete output_frame;
237                         bitmap = 0;
238                         output_frame = 0;
240 // Blank only if size changed
241                         if(size_change)
242                         {
243                                 output->canvas->set_color(BLACK);
244                                 output->canvas->draw_box(0, 0, output->w, output->h);
245                                 output->canvas->flash();
246                         }
247                 }
248                 else
249 // Update the ring buffer
250                 if(bitmap_type == BITMAP_PRIMARY)
251                 {
253 //printf("VDeviceX11::new_output_buffer\n");
254                         output_frame->set_memory((unsigned char*)bitmap->get_data() /* + bitmap->get_shm_offset() */,
255                                                 bitmap->get_y_offset(),
256                                                 bitmap->get_u_offset(),
257                                                 bitmap->get_v_offset());
258                 }
259         }
260 //TRACE("VDeviceX11::new_output_buffer 10");
262 // Create new bitmap
263         if(!bitmap)
264         {
265 // Try hardware accelerated
266                 switch(best_colormodel)
267                 {
268                         case BC_YUV420P:
269 //TRACE("VDeviceX11::new_output_buffer 10");
270                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
271                                         output->canvas->accel_available(best_colormodel, 0))
272                                 {
273 //TRACE("VDeviceX11::new_output_buffer 20");
274                                         bitmap = new BC_Bitmap(output->canvas, 
275                                                 device->out_w,
276                                                 device->out_h,
277                                                 best_colormodel,
278                                                 1);
279 //TRACE("VDeviceX11::new_output_buffer 30");
280                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
281                                                 bitmap->get_y_offset(),
282                                                 bitmap->get_u_offset(),
283                                                 bitmap->get_v_offset(),
284                                                 device->out_w,
285                                                 device->out_h,
286                                                 best_colormodel);
287                                         bitmap_type = BITMAP_PRIMARY;
288                                 }
289                                 break;
291                         case BC_YUV422P:
292                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
293                                         output->canvas->accel_available(best_colormodel, 0))
294                                 {
295                                         bitmap = new BC_Bitmap(output->canvas, 
296                                                 device->out_w,
297                                                 device->out_h,
298                                                 best_colormodel,
299                                                 1);
300                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
301                                                 bitmap->get_y_offset(),
302                                                 bitmap->get_u_offset(),
303                                                 bitmap->get_v_offset(),
304                                                 device->out_w,
305                                                 device->out_h,
306                                                 best_colormodel);
307                                         bitmap_type = BITMAP_PRIMARY;
308                                 }
309                                 else
310                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
311                                         output->canvas->accel_available(BC_YUV422, 0))
312                                 {
313                                         bitmap = new BC_Bitmap(output->canvas, 
314                                                 device->out_w,
315                                                 device->out_h,
316                                                 BC_YUV422,
317                                                 1);
318                                         bitmap_type = BITMAP_TEMP;
319                                 }
320                                 break;
322                         case BC_YUV422:
323                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
324                                         output->canvas->accel_available(best_colormodel, 0))
325                                 {
326                                         bitmap = new BC_Bitmap(output->canvas, 
327                                                 device->out_w,
328                                                 device->out_h,
329                                                 best_colormodel,
330                                                 1);
331                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
332                                                 bitmap->get_y_offset(),
333                                                 bitmap->get_u_offset(),
334                                                 bitmap->get_v_offset(),
335                                                 device->out_w,
336                                                 device->out_h,
337                                                 best_colormodel);
338                                         bitmap_type = BITMAP_PRIMARY;
339                                 }
340                                 else
341                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
342                                         output->canvas->accel_available(BC_YUV422P, 0))
343                                 {
344                                         bitmap = new BC_Bitmap(output->canvas, 
345                                                 device->out_w,
346                                                 device->out_h,
347                                                 BC_YUV422P,
348                                                 1);
349                                         bitmap_type = BITMAP_TEMP;
350                                 }
351                                 break;
352                 }
354 // Not accelerated --- use specified Format/Video/Color model instead
355                 if(!bitmap)
356                 {
357                         best_colormodel = output->canvas->get_color_model();
358                         bitmap = new BC_Bitmap(output->canvas, 
359                                 output->canvas->get_w(),
360                                 output->canvas->get_h(),
361                                 best_colormodel,
362                                 1);
363                         bitmap_type = BITMAP_TEMP;
364                 }
366                 if(bitmap_type == BITMAP_TEMP)
367                 {
368 // Intermediate frame
369                         output_frame = new VFrame(0, 
370                                 device->out_w,
371                                 device->out_h,
372                                 colormodel);
373                         bitmap_type = BITMAP_TEMP;
374                 }
375                 color_model_selected = 1;
376         }
378 //TRACE("VDeviceX11::new_output_buffer 100");
380 // Fill arguments
381         if(bitmap_type == BITMAP_PRIMARY)
382         {
383 // Only useful if the primary is RGB888 which XFree86 never uses.
384                 output_frame->set_shm_offset(bitmap->get_shm_offset());
385         }
386         else
387         if(bitmap_type == BITMAP_TEMP)
388         {
389                 output_frame->set_shm_offset(0);
390         }
392 //printf("VDeviceX11::new_output_buffer 200\n");
394 // Temporary until multichannel X
395         output_channels[0] = output_frame;
397         output->canvas->unlock_window();
402 int VDeviceX11::start_playback()
404 // Record window is initialized when its monitor starts.
405         if(!device->single_frame)
406                 output->start_video();
407         return 0;
410 int VDeviceX11::stop_playback()
412         if(!device->single_frame)
413                 output->stop_video();
414 // Record window goes back to monitoring
415 // get the last frame played and store it in the video_out
416         return 0;
419 int VDeviceX11::write_buffer(VFrame **output_channels, EDL *edl)
421         int i = 0;
423 // The reason for not drawing single frame is that it is _always_ drawn 
424 // when drawing draw_refresh in cwindowgui and vwindowgui
425         if (device->single_frame) 
426                 return 0;
428         output->canvas->lock_window("VDeviceX11::write_buffer");
429         output->get_transfers(edl, 
430                 in_x, 
431                 in_y, 
432                 in_w, 
433                 in_h, 
434                 out_x, 
435                 out_y, 
436                 out_w, 
437                 out_h,
438                 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_w() : -1,
439                 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_h() : -1);
441 //output->canvas->unlock_window();
442 //return 0;
443 // printf("VDeviceX11::write_buffer 2 %d\n", bitmap_type);
444 // for(int j = 0; j < output_channels[0]->get_w() * 3 * 5; j++)
445 //      output_channels[0]->get_rows()[0][j] = 255;
447 // Convert colormodel
448         if(bitmap_type == BITMAP_TEMP)
449         {
450 // printf("VDeviceX11::write_buffer 1 %d %d, %d %d %d %d -> %d %d %d %d\n",
451 //                      output->w,
452 //                      output->h,
453 //                      in_x, 
454 //                      in_y, 
455 //                      in_w, 
456 //                      in_h,
457 //                      out_x, 
458 //                      out_y, 
459 //                      out_w, 
460 //                      out_h );fflush(stdout);
462 //printf("VDeviceX11::write_buffer 2\n");
464 //printf("VDeviceX11::write_buffer 3 %p %p\n", bitmap->get_row_pointers(), output_channels[0]->get_rows());
466                 if(bitmap->hardware_scaling())
467                 {
468                         cmodel_transfer(bitmap->get_row_pointers(), 
469                                 output_channels[0]->get_rows(),
470                                 0,
471                                 0,
472                                 0,
473                                 output_channels[0]->get_y(),
474                                 output_channels[0]->get_u(),
475                                 output_channels[0]->get_v(),
476                                 0, 
477                                 0, 
478                                 output_channels[0]->get_w(), 
479                                 output_channels[0]->get_h(),
480                                 0, 
481                                 0, 
482                                 bitmap->get_w(), 
483                                 bitmap->get_h(),
484                                 output_channels[0]->get_color_model(), 
485                                 bitmap->get_color_model(),
486                                 0,
487                                 output_channels[0]->get_w(),
488                                 bitmap->get_w());
489                 }
490                 else
491                 {
492                         cmodel_transfer(bitmap->get_row_pointers(), 
493                                 output_channels[0]->get_rows(),
494                                 0,
495                                 0,
496                                 0,
497                                 output_channels[0]->get_y(),
498                                 output_channels[0]->get_u(),
499                                 output_channels[0]->get_v(),
500                                 in_x, 
501                                 in_y, 
502                                 in_w, 
503                                 in_h,
504                                 0, 
505                                 0, 
506                                 out_w, 
507                                 out_h,
508                                 output_channels[0]->get_color_model(), 
509                                 bitmap->get_color_model(),
510                                 0,
511                                 output_channels[0]->get_w(),
512                                 bitmap->get_w());
513                 }
514         }
516 //printf("VDeviceX11::write_buffer 4 %p\n", bitmap);
517 //for(i = 0; i < 1000; i += 4) bitmap->get_data()[i] = 128;
518 //printf("VDeviceX11::write_buffer 2 %d %d %d\n", bitmap_type, 
519 //      bitmap->get_color_model(), 
520 //      output->get_color_model());fflush(stdout);
521 // printf("VDeviceX11::write_buffer 2 %d %d, %d %d %d %d -> %d %d %d %d\n",
522 //                      output->w,
523 //                      output->h,
524 //                      in_x, 
525 //                      in_y, 
526 //                      in_w, 
527 //                      in_h,
528 //                      out_x, 
529 //                      out_y, 
530 //                      out_w, 
531 //                      out_h);
534 // Select field if using field mode.  This may be a useful feature later on
535 // but currently it's being superceded by the heroine 60 encoding.
536 // Doing time base conversion in the display routine produces 
537 // pretty big compression artifacts.  It also requires implementing a
538 // different transform for each X visual.
539         if(device->out_config->x11_use_fields)
540         {
541         }
545 // Cause X server to display it
546         if(bitmap->hardware_scaling())
547         {
548                 output->canvas->draw_bitmap(bitmap,
549                         !device->single_frame,
550                         out_x, 
551                         out_y, 
552                         out_w, 
553                         out_h,
554                         in_x, 
555                         in_y, 
556                         in_w, 
557                         in_h,
558                         0);
559         }
560         else
561         {
562                 output->canvas->draw_bitmap(bitmap,
563                         !device->single_frame,
564                         out_x, 
565                         out_y, 
566                         out_w, 
567                         out_h,
568                         0, 
569                         0, 
570                         out_w, 
571                         out_h,
572                         0);
573         }
576         output->canvas->unlock_window();
577         return 0;