home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / guicast / bccapture.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  5KB  |  216 lines

  1. #include "bccapture.h"
  2. #include "bcresources.h"
  3. #include "bcwindowbase.h"
  4. #include "colormodels.h"
  5. #include "vframe.h"
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <X11/Xutil.h>
  9.  
  10.  
  11.  
  12.  
  13. // Byte orders:
  14. // 24 bpp packed:         bgr
  15. // 24 bpp unpacked:       0bgr
  16.  
  17.  
  18. BC_Capture::BC_Capture(int w, int h, char *display_path)
  19. {
  20.     this->w = w;
  21.     this->h = h;
  22.  
  23.     data = 0;
  24.     use_shm = 1;
  25.     init_window(display_path);
  26.     allocate_data();
  27. }
  28.  
  29.  
  30. BC_Capture::~BC_Capture()
  31. {
  32.     delete_data();
  33.     XCloseDisplay(display);
  34. }
  35.  
  36. int BC_Capture::init_window(char *display_path)
  37. {
  38.     if(display_path && display_path[0] == 0) display_path = NULL;
  39.     if((display = XOpenDisplay(display_path)) == NULL)
  40.     {
  41.           printf("cannot connect to X server.\n");
  42.           if(getenv("DISPLAY") == NULL)
  43.             printf("'DISPLAY' environment variable not set.\n");
  44.           exit(-1);
  45.         return 1;
  46.      }
  47.  
  48.     screen = DefaultScreen(display);
  49.     rootwin = RootWindow(display, screen);
  50.     vis = DefaultVisual(display, screen);
  51.     default_depth = DefaultDepth(display, screen);
  52.     client_byte_order = (*(unsigned BCBASE_INT32*)"a   ") & 0x00000001;
  53.     server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
  54.     bitmap_color_model = BC_WindowBase::evaluate_color_model(client_byte_order, server_byte_order, default_depth);
  55.  
  56. // test shared memory
  57. // This doesn't ensure the X Server is on the local host
  58.     if(use_shm && !XShmQueryExtension(display))
  59.     {
  60.         use_shm = 0;
  61.     }
  62.     return 0;
  63. }
  64.  
  65.  
  66. int BC_Capture::allocate_data()
  67. {
  68. // try shared memory
  69.     if(!display) return 1;
  70.     if(use_shm)
  71.     {
  72.         ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h);
  73.  
  74.         shm_info.shmid = shmget(IPC_PRIVATE, h * ximage->bytes_per_line, IPC_CREAT | 0777);
  75.         if(shm_info.shmid < 0) perror("BC_Capture::allocate_data shmget");
  76.         data = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
  77.         shmctl(shm_info.shmid, IPC_RMID, 0);
  78.         ximage->data = shm_info.shmaddr = (char*)data;  // setting ximage->data stops BadValue
  79.         shm_info.readOnly = 0;
  80.  
  81. // Crashes here if remote server.
  82.         BC_Resources::error = 0;
  83.         XShmAttach(display, &shm_info);
  84.         XSync(display, False);
  85.         if(BC_Resources::error)
  86.         {
  87.             XDestroyImage(ximage);
  88.             shmdt(shm_info.shmaddr);
  89.             use_shm = 0;
  90.         }
  91.     }
  92.  
  93.     if(!use_shm)
  94.     {
  95. // need to use bytes_per_line for some X servers
  96.         data = 0;
  97.         ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
  98.         data = (unsigned char*)malloc(h * ximage->bytes_per_line);
  99.         XDestroyImage(ximage);
  100.  
  101.         ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
  102.     }
  103.  
  104.     row_data = new unsigned char*[h];
  105.     for(int i = 0; i < h; i++)
  106.     {
  107.         row_data[i] = &data[i * ximage->bytes_per_line];
  108.     }
  109. // This differs from the depth parameter of the top_level.
  110.     bits_per_pixel = ximage->bits_per_pixel;
  111.     return 0;
  112. }
  113.  
  114. int BC_Capture::delete_data()
  115. {
  116.     if(!display) return 1;
  117.     if(data)
  118.     {
  119.         if(use_shm)
  120.         {
  121.             XShmDetach(display, &shm_info);
  122.             XDestroyImage(ximage);
  123.             shmdt(shm_info.shmaddr);
  124.         }
  125.         else
  126.         {
  127.             XDestroyImage(ximage);
  128.         }
  129.  
  130. // data is automatically freed by XDestroyImage
  131.         data = 0;
  132.         delete row_data;
  133.     }
  134.     return 0;
  135. }
  136.  
  137.  
  138. int BC_Capture::get_w() { return w; }
  139. int BC_Capture::get_h() { return h; }
  140.  
  141. // Capture a frame from the screen
  142. #define CAPTURE_FRAME_HEAD \
  143.     for(int i = 0; i < h; i++) \
  144.     { \
  145.         unsigned char *input_row = row_data[i]; \
  146.         unsigned char *output_row = (unsigned char*)frame->get_rows()[i]; \
  147.         for(int j = 0; j < w; j++) \
  148.         {
  149.  
  150. #define CAPTURE_FRAME_TAIL \
  151.         } \
  152.     }
  153.  
  154.  
  155.  
  156. int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1)
  157. {
  158.     if(!display) return 1;
  159.     if(x1 < 0) x1 = 0;
  160.     if(y1 < 0) y1 = 0;
  161.     if(x1 > get_top_w() - w) x1 = get_top_w() - w;
  162.     if(y1 > get_top_h() - h) y1 = get_top_h() - h;
  163.  
  164.  
  165. // Read the raw data
  166.     if(use_shm)
  167.         XShmGetImage(display, rootwin, ximage, x1, y1, 0xffffffff);
  168.     else
  169.         XGetSubImage(display, rootwin, x1, y1, w, h, 0xffffffff, ZPixmap, ximage, 0, 0);
  170.  
  171. // Convert to VFrame
  172.     switch(frame->get_color_model())
  173.     {
  174.         case BC_RGB888:
  175.             switch(bitmap_color_model)
  176.             {
  177.                 case BC_RGB8:
  178.                     break;
  179.                 
  180.                 case BC_BGR565:
  181.                 case BC_RGB565:
  182.                     CAPTURE_FRAME_HEAD
  183.                     import_RGB565_to_RGB888(output_row, input_row);
  184.                     CAPTURE_FRAME_TAIL
  185.                     break;
  186.                 
  187.                 case BC_BGR888:
  188.                     CAPTURE_FRAME_HEAD
  189.                     import_BGR888_to_RGB888(output_row, input_row);
  190.                     CAPTURE_FRAME_TAIL
  191.                     break;
  192.                 
  193.                 case BC_BGR8888:
  194.                     CAPTURE_FRAME_HEAD
  195.                     import_BGR8888_to_RGB888(output_row, input_row);
  196.                     CAPTURE_FRAME_TAIL
  197.                     break;
  198.             }
  199.             break;
  200.     }
  201.  
  202.     return 0;
  203. }
  204.  
  205. int BC_Capture::get_top_w()
  206. {
  207.     Screen *screen_ptr = XDefaultScreenOfDisplay(display);
  208.     return WidthOfScreen(screen_ptr);
  209. }
  210.  
  211. int BC_Capture::get_top_h()
  212. {
  213.     Screen *screen_ptr = XDefaultScreenOfDisplay(display);
  214.     return HeightOfScreen(screen_ptr);
  215. }
  216.