merged hv7 mod
[goodguy/history.git] / cinelerra-5.1 / guicast / bccapture.C
index 993cfe14fbc3279ee1cbf7c08943608416d5e441..e955a52730b03ed51f80c60dd21c5baa722cb1fc 100644 (file)
 #include "bcresources.h"
 #include "bcwindowbase.h"
 #include "bccmodels.h"
+#include "bccolors.h"
+#include "clip.h"
 #include "language.h"
 #include "vframe.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <X11/Xutil.h>
-
-
-
-
+#include <X11/extensions/Xfixes.h>
 
 // Byte orders:
 // 24 bpp packed:         bgr
@@ -59,11 +58,10 @@ BC_Capture::~BC_Capture()
 int BC_Capture::init_window(const char *display_path)
 {
        int bits_per_pixel;
-       if(display_path && display_path[0] == 0) display_path = NULL;
-       if((display = XOpenDisplay(display_path)) == NULL)
-       {
+       if( display_path && display_path[0] == 0 ) display_path = NULL;
+       if( (display = XOpenDisplay(display_path)) == NULL ) {
                printf(_("cannot connect to X server.\n"));
-               if(getenv("DISPLAY") == NULL)
+               if( getenv("DISPLAY") == NULL )
                printf(_("'DISPLAY' environment variable not set.\n"));
                exit(-1);
                return 1;
@@ -93,8 +91,7 @@ int BC_Capture::init_window(const char *display_path)
 
 // test shared memory
 // This doesn't ensure the X Server is on the local host
-    if(use_shm && !XShmQueryExtension(display))
-    {
+    if( use_shm && !XShmQueryExtension(display) ) {
         use_shm = 0;
     }
        return 0;
@@ -104,14 +101,12 @@ int BC_Capture::init_window(const char *display_path)
 int BC_Capture::allocate_data()
 {
 // try shared memory
-       if(!display) return 1;
-    if(use_shm)
-       {
+       if( !display ) return 1;
+    if( use_shm ) {
            ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h);
 
                shm_info.shmid = shmget(IPC_PRIVATE, h * ximage->bytes_per_line, IPC_CREAT | 0600);
-               if(shm_info.shmid == -1)
-               {
+               if( shm_info.shmid == -1 ) {
                        perror("BC_Capture::allocate_data shmget");
                        abort();
                }
@@ -124,16 +119,14 @@ int BC_Capture::allocate_data()
                BC_Resources::error = 0;
                XShmAttach(display, &shm_info);
        XSync(display, False);
-               if(BC_Resources::error)
-               {
+               if( BC_Resources::error ) {
                        XDestroyImage(ximage);
                        shmdt(shm_info.shmaddr);
                        use_shm = 0;
                }
        }
 
-       if(!use_shm)
-       {
+       if( !use_shm ) {
 // need to use bytes_per_line for some X servers
                data = 0;
                ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
@@ -144,8 +137,7 @@ int BC_Capture::allocate_data()
        }
 
        row_data = new unsigned char*[h];
-       for(int i = 0; i < h; i++)
-       {
+       for( int i = 0; i < h; i++ ) {
                row_data[i] = &data[i * ximage->bytes_per_line];
        }
 // This differs from the depth parameter of the top_level.
@@ -155,17 +147,14 @@ int BC_Capture::allocate_data()
 
 int BC_Capture::delete_data()
 {
-       if(!display) return 1;
-       if(data)
-       {
-               if(use_shm)
-               {
+       if( !display ) return 1;
+       if( data ) {
+               if( use_shm ) {
                        XShmDetach(display, &shm_info);
                        XDestroyImage(ximage);
                        shmdt(shm_info.shmaddr);
                }
-               else
-               {
+               else {
                        XDestroyImage(ximage);
                }
 
@@ -181,31 +170,22 @@ int BC_Capture::get_w() { return w; }
 int BC_Capture::get_h() { return h; }
 
 // Capture a frame from the screen
-#define CAPTURE_FRAME_HEAD \
-       for(int i = 0; i < h; i++) \
-       { \
-               unsigned char *input_row = row_data[i]; \
-               unsigned char *output_row = (unsigned char*)frame->get_rows()[i]; \
-               for(int j = 0; j < w; j++) \
-               {
-
-#define CAPTURE_FRAME_TAIL \
-               } \
-       }
+#define RGB_TO_YUV(y, u, v, r, g, b) { \
+ YUV::yuv.rgb_to_yuv_8(r, g, b, y, u, v); \
+ bclamp(y, 0,0xff); bclamp(u, 0,0xff); bclamp(v, 0,0xff); }
 
-
-
-int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1)
+int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1, 
+       int do_cursor) // the scale of the cursor if nonzero
 {
-       if(!display) return 1;
-       if(x1 < 0) x1 = 0;
-       if(y1 < 0) y1 = 0;
-       if(x1 > get_top_w() - w) x1 = get_top_w() - w;
-       if(y1 > get_top_h() - h) y1 = get_top_h() - h;
+       if( !display ) return 1;
+       if( x1 < 0 ) x1 = 0;
+       if( y1 < 0 ) y1 = 0;
+       if( x1 > get_top_w() - w ) x1 = get_top_w() - w;
+       if( y1 > get_top_h() - h ) y1 = get_top_h() - h;
 
 
 // Read the raw data
-       if(use_shm)
+       if( use_shm )
                XShmGetImage(display, rootwin, ximage, x1, y1, 0xffffffff);
        else
                XGetSubImage(display, rootwin, x1, y1, w, h, 0xffffffff, ZPixmap, ximage, 0, 0);
@@ -216,6 +196,72 @@ int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1)
                frame->get_w(), frame->get_h(),
                bitmap_color_model, frame->get_color_model(),
                0, frame->get_w(), w);
+       
+       if( do_cursor ) {
+               XFixesCursorImage *cursor;
+               cursor = XFixesGetCursorImage(display);
+               if( cursor ) {
+//printf("BC_Capture::capture_frame %d cursor=%p colormodel=%d\n", 
+// __LINE__, cursor, frame->get_color_model());
+                       int scale = do_cursor;
+                       int cursor_x = cursor->x - x1 - cursor->xhot * scale;
+                       int cursor_y = cursor->y - y1 - cursor->yhot * scale;
+                       int w = frame->get_w();
+                       int h = frame->get_h();
+                       for( int i = 0; i < cursor->height; i++ ) {
+                               for( int yscale = 0; yscale < scale; yscale++ ) {
+                                       if( cursor_y + i * scale + yscale >= 0 && 
+                                               cursor_y + i * scale + yscale < h ) {
+                                               unsigned char *src = (unsigned char*)(cursor->pixels + 
+                                                       i * cursor->width);
+                                               int dst_y = cursor_y + i * scale + yscale;
+                                               int dst_x = cursor_x;
+                                               for( int j = 0; j < cursor->width; j++ ) {
+                                                       for( int xscale = 0; xscale < scale ; xscale++ ) {
+                                                               if( cursor_x + j * scale + xscale >= 0 && 
+                                                                       cursor_x + j * scale + xscale < w ) {
+                                                                       int a = src[3];
+                                                                       int invert_a = 0xff - a;
+                                                                       int r = src[2];
+                                                                       int g = src[1];
+                                                                       int b = src[0];
+                                                                       switch( frame->get_color_model() ) {
+                                                                       case BC_RGB888: {
+                                                                               unsigned char *dst = frame->get_rows()[dst_y] +
+                                                                                       dst_x * 3;
+                                                                               dst[0] = (r * a + dst[0] * invert_a) / 0xff;
+                                                                               dst[1] = (g * a + dst[1] * invert_a) / 0xff;
+                                                                               dst[2] = (b * a + dst[2] * invert_a) / 0xff;
+                                                                               break; }
+
+                                                                       case BC_YUV420P: {
+                                                                               unsigned char *dst_y_ = frame->get_y() + 
+                                                                                       dst_y * w + dst_x;
+                                                                               unsigned char *dst_u = frame->get_u() + 
+                                                                                       (dst_y / 2) * (w / 2) + (dst_x / 2);
+                                                                               unsigned char *dst_v = frame->get_v() + 
+                                                                                       (dst_y / 2) * (w / 2) + (dst_x / 2);
+                                                                               int y, u, v;
+                                                                               RGB_TO_YUV(y, u, v, r, g, b);
+                                                                                       
+                                                                               *dst_y_ = (y * a + *dst_y_ * invert_a) / 0xff;
+                                                                               *dst_u = (u * a + *dst_u * invert_a) / 0xff;
+                                                                               *dst_v = (v * a + *dst_v * invert_a) / 0xff;
+                                                                               break; }
+                                                                       }
+                                                               }
+                                                               dst_x++;
+                                                       }
+                                                       src += sizeof(long);
+                                               }
+                                       }
+                               }
+                       }
+
+// This frees cursor->pixels
+                       XFree(cursor);
+               }
+       }
 
        return 0;
 }