r499: This commit was manufactured by cvs2svn to create tag 'r1_2_1-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / vdevicex11.C
blobb74eaeb17248586d039cb70018976493e6381f66
1 #include "assets.h"
2 #include "bccapture.h"
3 #include "canvas.h"
4 #include "colormodels.h"
5 #include "mwindow.h"
6 #include "playbackconfig.h"
7 #include "preferences.h"
8 #include "recordconfig.h"
9 #include "strategies.inc"
10 #include "vdevicex11.h"
11 #include "vframe.h"
12 #include "videodevice.h"
13 #include "videowindow.h"
14 #include "videowindowgui.h"
16 #include <string.h>
17 #include <unistd.h>
19 VDeviceX11::VDeviceX11(VideoDevice *device, Canvas *output)
20  : VDeviceBase(device)
22         reset_parameters();
23         this->output = output;
26 VDeviceX11::~VDeviceX11()
28         close_all();
31 int VDeviceX11::reset_parameters()
33         output_frame = 0;
34         bitmap = 0;
35         bitmap_w = 0;
36         bitmap_h = 0;
37         output = 0;
38         in_x = 0;
39         in_y = 0;
40         in_w = 0;
41         in_h = 0;
42         out_x = 0;
43         out_y = 0;
44         out_w = 0;
45         out_h = 0;
46         capture_bitmap = 0;
47         color_model_selected = 0;
48         return 0;
51 int VDeviceX11::open_input()
53 //printf("VDeviceX11::open_input 1\n");
54         capture_bitmap = new BC_Capture(device->in_config->w, 
55                 device->in_config->h,
56                 device->in_config->screencapture_display);
57 //printf("VDeviceX11::open_input 2\n");
58         
59         return 0;
62 int VDeviceX11::open_output()
64         if(output && !device->single_frame) 
65                 output->canvas->start_video();
66         return 0;
70 int VDeviceX11::output_visible()
72         if(!output || output->canvas->get_hidden()) 
73                 return 0; 
74         else 
75                 return 1;
79 int VDeviceX11::close_all()
81         if(output)
82         {
83                 output->canvas->lock_window("VDeviceX11::close_all");
84         }
86         if(output && output_frame)
87         {
88 // Copy picture to persistent frame buffer with conversion to flat colormodel
89                 if(output->refresh_frame &&
90                         (output->refresh_frame->get_w() != device->out_w ||
91                         output->refresh_frame->get_h() != device->out_h ||
92                         output->refresh_frame->get_color_model() != output_frame->get_color_model()))
93                 {
94                         delete output->refresh_frame;
95                         output->refresh_frame = 0;
96                 }
98                 if(!output->refresh_frame)
99                 {
100                         output->refresh_frame = new VFrame(0,
101                                 device->out_w,
102                                 device->out_h,
103                                 output_frame->get_color_model());
104                 }
106                 if(!device->single_frame)
107                 {
108                         output->canvas->stop_video();
109                 }
111                 output->refresh_frame->copy_from(output_frame);
113                 output->draw_refresh();
114         }
116         if(bitmap)
117         {
118                 delete bitmap;
119                 delete output_frame;
120                 bitmap = 0;
121         }
123         if(capture_bitmap) delete capture_bitmap;
125         if(output)
126         {
127                 output->canvas->unlock_window();
128         }
131         reset_parameters();
132         return 0;
135 int VDeviceX11::read_buffer(VFrame *frame)
137         capture_bitmap->capture_frame(frame, device->input_x, device->input_y);
138         return 0;
142 int VDeviceX11::get_best_colormodel(Asset *asset)
144         return BC_RGB888;
148 int VDeviceX11::get_best_colormodel(int colormodel)
150         int result = -1;
151         if(!device->single_frame)
152         {
153                 switch(colormodel)
154                 {
155                         case BC_YUV420P:
156                         case BC_YUV422P:
157                         case BC_YUV422:
158                                 result = colormodel;
159                                 break;
160                 }
161         }
163         if(result < 0)
164         {
165                 switch(colormodel)
166                 {
167                         case BC_RGB888:
168                         case BC_RGBA8888:
169                         case BC_RGB161616:
170                         case BC_RGBA16161616:
171                         case BC_YUV888:
172                         case BC_YUVA8888:
173                         case BC_YUV161616:
174                         case BC_YUVA16161616:
175                                 result = colormodel;
176                                 break;
178                         default:
179                                 result = output->canvas->get_color_model();
180                                 break;
181                 }
182         }
184 //printf("VDeviceX11::get_best_colormodel %d %d %d\n", device->single_frame, colormodel, result);
185         return result;
189 void VDeviceX11::new_output_buffer(VFrame **output_channels, int colormodel)
191         for(int i = 0; i < MAX_CHANNELS; i++)
192                 output_channels[i] = 0;
193 //printf("VDeviceX11::new_output_buffer 1\n");
195 // Get the best colormodel the display can handle.
196         int best_colormodel = get_best_colormodel(colormodel);
197 //printf("VDeviceX11::new_output_buffer 2 %d\n", best_colormodel);
199 // Conform existing bitmap to new colormodel and output size
200         if(bitmap)
201         {
202 // Restart if output size changed or output colormodel changed
203                 if(!color_model_selected ||
204                         (!bitmap->hardware_scaling() && 
205                                 (bitmap->get_w() != output->canvas->get_w() ||
206                                 bitmap->get_h() != output->canvas->get_h())) ||
207                         colormodel != output_frame->get_color_model())
208                 {
209                         int size_change = (bitmap->get_w() != output->canvas->get_w() ||
210                                 bitmap->get_h() != output->canvas->get_h());
211                         delete bitmap;
212                         delete output_frame;
213                         bitmap = 0;
214                         output_frame = 0;
216 // Blank only if size changed
217                         if(size_change)
218                         {
219                                 output->canvas->set_color(BLACK);
220                                 output->canvas->draw_box(0, 0, output->w, output->h);
221                                 output->canvas->flash();
222                         }
223                 }
224                 else
225 // Update the ring buffer
226                 if(bitmap_type == BITMAP_PRIMARY)
227                 {
229 //printf("VDeviceX11::new_output_buffer\n");
230                         output_frame->set_memory((unsigned char*)bitmap->get_data() /* + bitmap->get_shm_offset() */,
231                                                 bitmap->get_y_offset(),
232                                                 bitmap->get_u_offset(),
233                                                 bitmap->get_v_offset());
234                 }
235         }
237 // Create new bitmap
238         if(!bitmap)
239         {
240 //printf("VDeviceX11::new_output_buffer 1 %d\n", best_colormodel);
241 // Try hardware accelerated
242                 switch(best_colormodel)
243                 {
244                         case BC_YUV420P:
245                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
246                                         output->canvas->accel_available(best_colormodel))
247                                 {
248                                         bitmap = new BC_Bitmap(output->canvas, 
249                                                 device->out_w,
250                                                 device->out_h,
251                                                 best_colormodel,
252                                                 1);
253                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
254                                                 bitmap->get_y_offset(),
255                                                 bitmap->get_u_offset(),
256                                                 bitmap->get_v_offset(),
257                                                 device->out_w,
258                                                 device->out_h,
259                                                 best_colormodel);
260                                         bitmap_type = BITMAP_PRIMARY;
261                                 }
262                                 break;
264                         case BC_YUV422P:
265                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
266                                         output->canvas->accel_available(best_colormodel))
267                                 {
268                                         bitmap = new BC_Bitmap(output->canvas, 
269                                                 device->out_w,
270                                                 device->out_h,
271                                                 best_colormodel,
272                                                 1);
273                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
274                                                 bitmap->get_y_offset(),
275                                                 bitmap->get_u_offset(),
276                                                 bitmap->get_v_offset(),
277                                                 device->out_w,
278                                                 device->out_h,
279                                                 best_colormodel);
280                                         bitmap_type = BITMAP_PRIMARY;
281                                 }
282                                 else
283                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
284                                         output->canvas->accel_available(BC_YUV422))
285                                 {
286                                         bitmap = new BC_Bitmap(output->canvas, 
287                                                 device->out_w,
288                                                 device->out_h,
289                                                 BC_YUV422,
290                                                 1);
291                                         bitmap_type = BITMAP_TEMP;
292                                 }
293                                 break;
295                         case BC_YUV422:
296 //printf("VDeviceX11::new_output_buffer 3\n");
297                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
298                                         output->canvas->accel_available(best_colormodel))
299                                 {
300 //printf("VDeviceX11::new_output_buffer 4\n");
301                                         bitmap = new BC_Bitmap(output->canvas, 
302                                                 device->out_w,
303                                                 device->out_h,
304                                                 best_colormodel,
305                                                 1);
306                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
307                                                 bitmap->get_y_offset(),
308                                                 bitmap->get_u_offset(),
309                                                 bitmap->get_v_offset(),
310                                                 device->out_w,
311                                                 device->out_h,
312                                                 best_colormodel);
313                                         bitmap_type = BITMAP_PRIMARY;
314                                 }
315                                 else
316                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
317                                         output->canvas->accel_available(BC_YUV422P))
318                                 {
319 //printf("VDeviceX11::new_output_buffer 5\n");
320                                         bitmap = new BC_Bitmap(output->canvas, 
321                                                 device->out_w,
322                                                 device->out_h,
323                                                 BC_YUV422P,
324                                                 1);
325 //printf("VDeviceX11::new_output_buffer 6\n");
326                                         bitmap_type = BITMAP_TEMP;
327 //printf("VDeviceX11::new_output_buffer 7\n");
328                                 }
329                                 break;
330                 }
331 //printf("VDeviceX11::new_output_buffer 8\n");
333 // Not accelerated --- use specified Format/Video/Color model instead
334                 if(!bitmap)
335                 {
336                         best_colormodel = output->canvas->get_color_model();
337                         bitmap = new BC_Bitmap(output->canvas, 
338                                 output->canvas->get_w(),
339                                 output->canvas->get_h(),
340                                 best_colormodel,
341                                 1);
342                         bitmap_type = BITMAP_TEMP;
343 //printf("VDeviceX11::new_output_buffer 9\n");
344                 }
346                 if(bitmap_type == BITMAP_TEMP)
347                 {
348 // Intermediate frame
349                         output_frame = new VFrame(0, 
350                                 device->out_w,
351                                 device->out_h,
352                                 colormodel);
353                         bitmap_type = BITMAP_TEMP;
354 //printf("VDeviceX11::new_output_buffer 10\n");
355                 }
356                 color_model_selected = 1;
357         }
358 //printf("VDeviceX11::new_output_buffer 11\n");
360 // Fill arguments
361         if(bitmap_type == BITMAP_PRIMARY)
362         {
363 // Only useful if the primary is RGB888 which XFree86 never uses.
364                 output_frame->set_shm_offset(bitmap->get_shm_offset());
365         }
366         else
367         if(bitmap_type == BITMAP_TEMP)
368         {
369                 output_frame->set_shm_offset(0);
370         }
371 //printf("VDeviceX11::new_output_buffer 12\n");
373 // Temporary until multichannel X
374         output_channels[0] = output_frame;
378 int VDeviceX11::start_playback()
380 // Record window is initialized when its monitor starts.
381         if(!device->single_frame)
382                 output->canvas->start_video();
383         return 0;
386 int VDeviceX11::stop_playback()
388         if(!device->single_frame)
389                 output->canvas->stop_video();
390 // Record window goes back to monitoring
391 // get the last frame played and store it in the video_out
392         return 0;
395 int VDeviceX11::write_buffer(VFrame **output_channels, EDL *edl)
397         int i = 0;
399 //printf("VDeviceX11::write_buffer 1\n");
400         output->canvas->lock_window("VDeviceX11::write_buffer");
401 //printf("VDeviceX11::write_buffer 2\n");
402         output->get_transfers(edl, 
403                 in_x, 
404                 in_y, 
405                 in_w, 
406                 in_h, 
407                 out_x, 
408                 out_y, 
409                 out_w, 
410                 out_h,
411                 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_w() : -1,
412                 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_h() : -1);
414 //output->canvas->unlock_window();
415 //return 0;
416 // printf("VDeviceX11::write_buffer 2 %d\n", bitmap_type);
417 // for(int j = 0; j < output_channels[0]->get_w() * 3 * 5; j++)
418 //      output_channels[0]->get_rows()[0][j] = 255;
420 // Convert colormodel
421         if(bitmap_type == BITMAP_TEMP)
422         {
423 // printf("VDeviceX11::write_buffer 1 %d %d, %d %d %d %d -> %d %d %d %d\n",
424 //                      output->w,
425 //                      output->h,
426 //                      in_x, 
427 //                      in_y, 
428 //                      in_w, 
429 //                      in_h,
430 //                      out_x, 
431 //                      out_y, 
432 //                      out_w, 
433 //                      out_h );fflush(stdout);
435 //printf("VDeviceX11::write_buffer 2\n");
437 //printf("VDeviceX11::write_buffer 3 %p %p\n", bitmap->get_row_pointers(), output_channels[0]->get_rows());
439                 if(bitmap->hardware_scaling())
440                 {
441                         cmodel_transfer(bitmap->get_row_pointers(), 
442                                 output_channels[0]->get_rows(),
443                                 0,
444                                 0,
445                                 0,
446                                 output_channels[0]->get_y(),
447                                 output_channels[0]->get_u(),
448                                 output_channels[0]->get_v(),
449                                 0, 
450                                 0, 
451                                 output_channels[0]->get_w(), 
452                                 output_channels[0]->get_h(),
453                                 0, 
454                                 0, 
455                                 bitmap->get_w(), 
456                                 bitmap->get_h(),
457                                 output_channels[0]->get_color_model(), 
458                                 bitmap->get_color_model(),
459                                 0,
460                                 output_channels[0]->get_w(),
461                                 bitmap->get_w());
462                 }
463                 else
464                 {
465                         cmodel_transfer(bitmap->get_row_pointers(), 
466                                 output_channels[0]->get_rows(),
467                                 0,
468                                 0,
469                                 0,
470                                 output_channels[0]->get_y(),
471                                 output_channels[0]->get_u(),
472                                 output_channels[0]->get_v(),
473                                 in_x, 
474                                 in_y, 
475                                 in_w, 
476                                 in_h,
477                                 0, 
478                                 0, 
479                                 out_w, 
480                                 out_h,
481                                 output_channels[0]->get_color_model(), 
482                                 bitmap->get_color_model(),
483                                 0,
484                                 output_channels[0]->get_w(),
485                                 bitmap->get_w());
486                 }
487         }
489 //printf("VDeviceX11::write_buffer 4 %p\n", bitmap);
490 //for(i = 0; i < 1000; i += 4) bitmap->get_data()[i] = 128;
491 //printf("VDeviceX11::write_buffer 2 %d %d %d\n", bitmap_type, 
492 //      bitmap->get_color_model(), 
493 //      output->get_color_model());fflush(stdout);
494 // printf("VDeviceX11::write_buffer 2 %d %d, %d %d %d %d -> %d %d %d %d\n",
495 //                      output->w,
496 //                      output->h,
497 //                      in_x, 
498 //                      in_y, 
499 //                      in_w, 
500 //                      in_h,
501 //                      out_x, 
502 //                      out_y, 
503 //                      out_w, 
504 //                      out_h);
507 // Select field if using field mode.  This may be a useful feature later on
508 // but currently it's being superceded by the heroine 60 encoding.
509 // Doing time base conversion in the display routine produces 
510 // pretty big compression artifacts.  It also requires implementing a
511 // different transform for each X visual.
512         if(device->out_config->x11_use_fields)
513         {
514         }
518 // Cause X server to display it
519         if(bitmap->hardware_scaling())
520         {
521                 output->canvas->draw_bitmap(bitmap,
522                         !device->single_frame,
523                         out_x, 
524                         out_y, 
525                         out_w, 
526                         out_h,
527                         in_x, 
528                         in_y, 
529                         in_w, 
530                         in_h,
531                         0);
532         }
533         else
534         {
535                 output->canvas->draw_bitmap(bitmap,
536                         !device->single_frame,
537                         out_x, 
538                         out_y, 
539                         out_w, 
540                         out_h,
541                         0, 
542                         0, 
543                         out_w, 
544                         out_h,
545                         0);
546         }
549 // In single frame mode we want the frame to display once along with overlays
550 // when the device is closed.  This prevents intermediate drawing with overlays
551 // from reading the obsolete back buffer before the device is closed.
553 //      if(device->single_frame)
554 //      {
555 //              output->canvas->flash();
556 //              output->canvas->flush();
557 //      }
559         output->canvas->unlock_window();
560 //printf("VDeviceX11::write_buffer 5\n");fflush(stdout);
561         return 0;