r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / vdevicex11.C
blobafd6702995b8014a6e61f5e0605b5ba4c55c0782
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         for(int i = 0; i < MAX_CHANNELS; i++)
214                 output_channels[i] = 0;
215 //printf("VDeviceX11::new_output_buffer 1\n");
217 // Get the best colormodel the display can handle.
218         int best_colormodel = get_best_colormodel(colormodel);
219 //printf("VDeviceX11::new_output_buffer 2 %d\n", best_colormodel);
221 // Conform existing bitmap to new colormodel and output size
222         if(bitmap)
223         {
224 // Restart if output size changed or output colormodel changed
225                 if(!color_model_selected ||
226                         (!bitmap->hardware_scaling() && 
227                                 (bitmap->get_w() != output->canvas->get_w() ||
228                                 bitmap->get_h() != output->canvas->get_h())) ||
229                         colormodel != output_frame->get_color_model())
230                 {
231                         int size_change = (bitmap->get_w() != output->canvas->get_w() ||
232                                 bitmap->get_h() != output->canvas->get_h());
233                         delete bitmap;
234                         delete output_frame;
235                         bitmap = 0;
236                         output_frame = 0;
238 // Blank only if size changed
239                         if(size_change)
240                         {
241                                 output->canvas->set_color(BLACK);
242                                 output->canvas->draw_box(0, 0, output->w, output->h);
243                                 output->canvas->flash();
244                         }
245                 }
246                 else
247 // Update the ring buffer
248                 if(bitmap_type == BITMAP_PRIMARY)
249                 {
251 //printf("VDeviceX11::new_output_buffer\n");
252                         output_frame->set_memory((unsigned char*)bitmap->get_data() /* + bitmap->get_shm_offset() */,
253                                                 bitmap->get_y_offset(),
254                                                 bitmap->get_u_offset(),
255                                                 bitmap->get_v_offset());
256                 }
257         }
259 // Create new bitmap
260         if(!bitmap)
261         {
262 //printf("VDeviceX11::new_output_buffer 1 %d\n", best_colormodel);
263 // Try hardware accelerated
264                 switch(best_colormodel)
265                 {
266                         case BC_YUV420P:
267                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
268                                         output->canvas->accel_available(best_colormodel))
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                                 break;
286                         case BC_YUV422P:
287                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
288                                         output->canvas->accel_available(best_colormodel))
289                                 {
290                                         bitmap = new BC_Bitmap(output->canvas, 
291                                                 device->out_w,
292                                                 device->out_h,
293                                                 best_colormodel,
294                                                 1);
295                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
296                                                 bitmap->get_y_offset(),
297                                                 bitmap->get_u_offset(),
298                                                 bitmap->get_v_offset(),
299                                                 device->out_w,
300                                                 device->out_h,
301                                                 best_colormodel);
302                                         bitmap_type = BITMAP_PRIMARY;
303                                 }
304                                 else
305                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
306                                         output->canvas->accel_available(BC_YUV422))
307                                 {
308                                         bitmap = new BC_Bitmap(output->canvas, 
309                                                 device->out_w,
310                                                 device->out_h,
311                                                 BC_YUV422,
312                                                 1);
313                                         bitmap_type = BITMAP_TEMP;
314                                 }
315                                 break;
317                         case BC_YUV422:
318 //printf("VDeviceX11::new_output_buffer 3\n");
319                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
320                                         output->canvas->accel_available(best_colormodel))
321                                 {
322 //printf("VDeviceX11::new_output_buffer 4\n");
323                                         bitmap = new BC_Bitmap(output->canvas, 
324                                                 device->out_w,
325                                                 device->out_h,
326                                                 best_colormodel,
327                                                 1);
328                                         output_frame = new VFrame((unsigned char*)bitmap->get_data() + bitmap->get_shm_offset(), 
329                                                 bitmap->get_y_offset(),
330                                                 bitmap->get_u_offset(),
331                                                 bitmap->get_v_offset(),
332                                                 device->out_w,
333                                                 device->out_h,
334                                                 best_colormodel);
335                                         bitmap_type = BITMAP_PRIMARY;
336                                 }
337                                 else
338                                 if(device->out_config->driver == PLAYBACK_X11_XV &&
339                                         output->canvas->accel_available(BC_YUV422P))
340                                 {
341 //printf("VDeviceX11::new_output_buffer 5\n");
342                                         bitmap = new BC_Bitmap(output->canvas, 
343                                                 device->out_w,
344                                                 device->out_h,
345                                                 BC_YUV422P,
346                                                 1);
347 //printf("VDeviceX11::new_output_buffer 6\n");
348                                         bitmap_type = BITMAP_TEMP;
349 //printf("VDeviceX11::new_output_buffer 7\n");
350                                 }
351                                 break;
352                 }
353 //printf("VDeviceX11::new_output_buffer 8\n");
355 // Not accelerated --- use specified Format/Video/Color model instead
356                 if(!bitmap)
357                 {
358                         best_colormodel = output->canvas->get_color_model();
359                         bitmap = new BC_Bitmap(output->canvas, 
360                                 output->canvas->get_w(),
361                                 output->canvas->get_h(),
362                                 best_colormodel,
363                                 1);
364                         bitmap_type = BITMAP_TEMP;
365 //printf("VDeviceX11::new_output_buffer 9\n");
366                 }
368                 if(bitmap_type == BITMAP_TEMP)
369                 {
370 // Intermediate frame
371                         output_frame = new VFrame(0, 
372                                 device->out_w,
373                                 device->out_h,
374                                 colormodel);
375                         bitmap_type = BITMAP_TEMP;
376 //printf("VDeviceX11::new_output_buffer 10\n");
377                 }
378                 color_model_selected = 1;
379         }
380 //printf("VDeviceX11::new_output_buffer 11\n");
382 // Fill arguments
383         if(bitmap_type == BITMAP_PRIMARY)
384         {
385 // Only useful if the primary is RGB888 which XFree86 never uses.
386                 output_frame->set_shm_offset(bitmap->get_shm_offset());
387         }
388         else
389         if(bitmap_type == BITMAP_TEMP)
390         {
391                 output_frame->set_shm_offset(0);
392         }
393 //printf("VDeviceX11::new_output_buffer 12\n");
395 // Temporary until multichannel X
396         output_channels[0] = output_frame;
400 int VDeviceX11::start_playback()
402 // Record window is initialized when its monitor starts.
403         if(!device->single_frame)
404                 output->start_video();
405         return 0;
408 int VDeviceX11::stop_playback()
410         if(!device->single_frame)
411                 output->stop_video();
412 // Record window goes back to monitoring
413 // get the last frame played and store it in the video_out
414         return 0;
417 int VDeviceX11::write_buffer(VFrame **output_channels, EDL *edl)
419         int i = 0;
421 // The reason for not drawing single frame is that it is _always_ drawn 
422 // when drawing draw_refresh in cwindowgui and vwindowgui
423         if (device->single_frame) 
424                 return 0;
426 //printf("VDeviceX11::write_buffer 1\n");
427         output->canvas->lock_window("VDeviceX11::write_buffer");
428 //printf("VDeviceX11::write_buffer 2\n");
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;