r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / vdevicex11.C
blob8850901f05c56802064bce7d54d03ec819a60b99
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                                         !output->use_scrollbars)
248                                 {
249                                         bitmap = new BC_Bitmap(output->canvas, 
250                                                 device->out_w,
251                                                 device->out_h,
252                                                 best_colormodel,
253                                                 1);
254                                         output_frame = new VFrame((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                                                 device->out_w,
259                                                 device->out_h,
260                                                 best_colormodel);
261                                         bitmap_type = BITMAP_PRIMARY;
262                                 }
263                                 break;
265                         case BC_YUV422P:
266                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
267                                         output->canvas->accel_available(best_colormodel) &&
268                                         !output->use_scrollbars)
269                                 {
270                                         bitmap = new BC_Bitmap(output->canvas, 
271                                                 device->out_w,
272                                                 device->out_h,
273                                                 best_colormodel,
274                                                 1);
275                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
276                                                 bitmap->get_y_offset(),
277                                                 bitmap->get_u_offset(),
278                                                 bitmap->get_v_offset(),
279                                                 device->out_w,
280                                                 device->out_h,
281                                                 best_colormodel);
282                                         bitmap_type = BITMAP_PRIMARY;
283                                 }
284                                 else
285                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
286                                         output->canvas->accel_available(BC_YUV422))
287                                 {
288                                         bitmap = new BC_Bitmap(output->canvas, 
289                                                 device->out_w,
290                                                 device->out_h,
291                                                 BC_YUV422,
292                                                 1);
293                                         bitmap_type = BITMAP_TEMP;
294                                 }
295                                 break;
297                         case BC_YUV422:
298 //printf("VDeviceX11::new_output_buffer 3\n");
299                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
300                                         output->canvas->accel_available(best_colormodel) &&
301                                         !output->use_scrollbars)
302                                 {
303 //printf("VDeviceX11::new_output_buffer 4\n");
304                                         bitmap = new BC_Bitmap(output->canvas, 
305                                                 device->out_w,
306                                                 device->out_h,
307                                                 best_colormodel,
308                                                 1);
309                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
310                                                 bitmap->get_y_offset(),
311                                                 bitmap->get_u_offset(),
312                                                 bitmap->get_v_offset(),
313                                                 device->out_w,
314                                                 device->out_h,
315                                                 best_colormodel);
316                                         bitmap_type = BITMAP_PRIMARY;
317                                 }
318                                 else
319                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
320                                         output->canvas->accel_available(BC_YUV422P))
321                                 {
322 //printf("VDeviceX11::new_output_buffer 5\n");
323                                         bitmap = new BC_Bitmap(output->canvas, 
324                                                 device->out_w,
325                                                 device->out_h,
326                                                 BC_YUV422P,
327                                                 1);
328 //printf("VDeviceX11::new_output_buffer 6\n");
329                                         bitmap_type = BITMAP_TEMP;
330 //printf("VDeviceX11::new_output_buffer 7\n");
331                                 }
332                                 break;
333                 }
334 //printf("VDeviceX11::new_output_buffer 8\n");
336 // Try default colormodel
337                 if(!bitmap)
338                 {
339                         best_colormodel = output->canvas->get_color_model();
340                         bitmap = new BC_Bitmap(output->canvas, 
341                                 output->canvas->get_w(),
342                                 output->canvas->get_h(),
343                                 best_colormodel,
344                                 1);
345                         bitmap_type = BITMAP_TEMP;
346 //printf("VDeviceX11::new_output_buffer 9\n");
347                 }
349                 if(bitmap_type == BITMAP_TEMP)
350                 {
351 // Intermediate frame
352                         output_frame = new VFrame(0, 
353                                 device->out_w,
354                                 device->out_h,
355                                 colormodel);
356                         bitmap_type = BITMAP_TEMP;
357 //printf("VDeviceX11::new_output_buffer 10\n");
358                 }
359                 color_model_selected = 1;
360         }
361 //printf("VDeviceX11::new_output_buffer 11\n");
363 // Fill arguments
364         if(bitmap_type == BITMAP_PRIMARY)
365         {
366 // Only useful if the primary is RGB888 which XFree86 never uses.
367                 output_frame->set_shm_offset(bitmap->get_shm_offset());
368         }
369         else
370         if(bitmap_type == BITMAP_TEMP)
371         {
372                 output_frame->set_shm_offset(0);
373         }
374 //printf("VDeviceX11::new_output_buffer 12\n");
376 // Temporary until multichannel X
377         output_channels[0] = output_frame;
381 int VDeviceX11::start_playback()
383 // Record window is initialized when its monitor starts.
384         if(!device->single_frame)
385                 output->canvas->start_video();
386         return 0;
389 int VDeviceX11::stop_playback()
391         if(!device->single_frame)
392                 output->canvas->stop_video();
393 // Record window goes back to monitoring
394 // get the last frame played and store it in the video_out
395         return 0;
398 int VDeviceX11::write_buffer(VFrame **output_channels, EDL *edl)
400         int i = 0;
402 //printf("VDeviceX11::write_buffer 1\n");
403         output->canvas->lock_window("VDeviceX11::write_buffer");
404 //printf("VDeviceX11::write_buffer 2\n");
405         output->get_transfers(edl, 
406                 in_x, 
407                 in_y, 
408                 in_w, 
409                 in_h, 
410                 out_x, 
411                 out_y, 
412                 out_w, 
413                 out_h,
414                 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_w() : -1,
415                 (bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) ? bitmap->get_h() : -1);
417 //output->canvas->unlock_window();
418 //return 0;
419 // printf("VDeviceX11::write_buffer 2 %d\n", bitmap_type);
420 // for(int j = 0; j < output_channels[0]->get_w() * 3 * 5; j++)
421 //      output_channels[0]->get_rows()[0][j] = 255;
423 // Convert colormodel
424         if(bitmap_type == BITMAP_TEMP)
425         {
426 // printf("VDeviceX11::write_buffer 1 %d %d, %d %d %d %d -> %d %d %d %d\n",
427 //                      output->w,
428 //                      output->h,
429 //                      in_x, 
430 //                      in_y, 
431 //                      in_w, 
432 //                      in_h,
433 //                      out_x, 
434 //                      out_y, 
435 //                      out_w, 
436 //                      out_h );fflush(stdout);
438 //printf("VDeviceX11::write_buffer 2\n");
440 //printf("VDeviceX11::write_buffer 3 %p %p\n", bitmap->get_row_pointers(), output_channels[0]->get_rows());
442                 if(bitmap->hardware_scaling())
443                 {
444                         cmodel_transfer(bitmap->get_row_pointers(), 
445                                 output_channels[0]->get_rows(),
446                                 0,
447                                 0,
448                                 0,
449                                 output_channels[0]->get_y(),
450                                 output_channels[0]->get_u(),
451                                 output_channels[0]->get_v(),
452                                 0, 
453                                 0, 
454                                 output_channels[0]->get_w(), 
455                                 output_channels[0]->get_h(),
456                                 0, 
457                                 0, 
458                                 bitmap->get_w(), 
459                                 bitmap->get_h(),
460                                 output_channels[0]->get_color_model(), 
461                                 bitmap->get_color_model(),
462                                 0,
463                                 output_channels[0]->get_w(),
464                                 bitmap->get_w());
465                 }
466                 else
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                                 in_x, 
477                                 in_y, 
478                                 in_w, 
479                                 in_h,
480                                 0, 
481                                 0, 
482                                 out_w, 
483                                 out_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         }
492 //printf("VDeviceX11::write_buffer 4 %p\n", bitmap);
493 //for(i = 0; i < 1000; i += 4) bitmap->get_data()[i] = 128;
494 //printf("VDeviceX11::write_buffer 2 %d %d %d\n", bitmap_type, 
495 //      bitmap->get_color_model(), 
496 //      output->get_color_model());fflush(stdout);
497 // printf("VDeviceX11::write_buffer 2 %d %d, %d %d %d %d -> %d %d %d %d\n",
498 //                      output->w,
499 //                      output->h,
500 //                      in_x, 
501 //                      in_y, 
502 //                      in_w, 
503 //                      in_h,
504 //                      out_x, 
505 //                      out_y, 
506 //                      out_w, 
507 //                      out_h);
510 // Select field if using field mode.  This may be a useful feature later on
511 // but currently it's being superceded by the heroine 60 encoding.
512 // Doing time base conversion in the display routine produces 
513 // pretty big compression artifacts.  It also requires implementing a
514 // different transform for each X visual.
515         if(device->out_config->x11_use_fields)
516         {
517         }
521 // Cause X server to display it
522         if(bitmap->hardware_scaling())
523         {
524                 output->canvas->draw_bitmap(bitmap,
525                         !device->single_frame,
526                         out_x, 
527                         out_y, 
528                         out_w, 
529                         out_h,
530                         in_x, 
531                         in_y, 
532                         in_w, 
533                         in_h,
534                         0);
535         }
536         else
537         {
538                 output->canvas->draw_bitmap(bitmap,
539                         !device->single_frame,
540                         out_x, 
541                         out_y, 
542                         out_w, 
543                         out_h,
544                         0, 
545                         0, 
546                         out_w, 
547                         out_h,
548                         0);
549         }
552 // In single frame mode we want the frame to display once along with overlays
553 // when the device is closed.  This prevents intermediate drawing with overlays
554 // from reading the obsolete back buffer before the device is closed.
556 //      if(device->single_frame)
557 //      {
558 //              output->canvas->flash();
559 //              output->canvas->flush();
560 //      }
562         output->canvas->unlock_window();
563 //printf("VDeviceX11::write_buffer 5\n");fflush(stdout);
564         return 0;