Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

bccapture.C

Go to the documentation of this file.
00001 #include "bccapture.h"
00002 #include "bcresources.h"
00003 #include "bcwindowbase.h"
00004 #include "colormodels.h"
00005 #include "language.h"
00006 #include "vframe.h"
00007 #include <stdlib.h>
00008 #include <stdio.h>
00009 #include <X11/Xutil.h>
00010 
00011 
00012 
00013 
00014 
00015 // Byte orders:
00016 // 24 bpp packed:         bgr
00017 // 24 bpp unpacked:       0bgr
00018 
00019 
00020 BC_Capture::BC_Capture(int w, int h, char *display_path)
00021 {
00022         this->w = w;
00023         this->h = h;
00024 
00025         data = 0;
00026         use_shm = 1;
00027         init_window(display_path);
00028         allocate_data();
00029 }
00030 
00031 
00032 BC_Capture::~BC_Capture()
00033 {
00034         delete_data();
00035         XCloseDisplay(display);
00036 }
00037 
00038 int BC_Capture::init_window(char *display_path)
00039 {
00040         int bits_per_pixel;
00041         if(display_path && display_path[0] == 0) display_path = NULL;
00042         if((display = XOpenDisplay(display_path)) == NULL)
00043         {
00044                 printf(_("cannot connect to X server.\n"));
00045                 if(getenv("DISPLAY") == NULL)
00046                 printf(_("'DISPLAY' environment variable not set.\n"));
00047                 exit(-1);
00048                 return 1;
00049         }
00050 
00051         screen = DefaultScreen(display);
00052         rootwin = RootWindow(display, screen);
00053         vis = DefaultVisual(display, screen);
00054         default_depth = DefaultDepth(display, screen);
00055         client_byte_order = (*(u_int32_t*)"a   ") & 0x00000001;
00056         server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
00057         char *data = 0;
00058         XImage *ximage;
00059         ximage = XCreateImage(display, 
00060                                         vis, 
00061                                         default_depth, 
00062                                         ZPixmap, 
00063                                         0, 
00064                                         data, 
00065                                         16, 
00066                                         16, 
00067                                         8, 
00068                                         0);
00069         bits_per_pixel = ximage->bits_per_pixel;
00070         XDestroyImage(ximage);
00071         bitmap_color_model = BC_WindowBase::evaluate_color_model(client_byte_order, server_byte_order, bits_per_pixel);
00072 
00073 // test shared memory
00074 // This doesn't ensure the X Server is on the local host
00075     if(use_shm && !XShmQueryExtension(display))
00076     {
00077         use_shm = 0;
00078     }
00079         return 0;
00080 }
00081 
00082 
00083 int BC_Capture::allocate_data()
00084 {
00085 // try shared memory
00086         if(!display) return 1;
00087     if(use_shm)
00088         {
00089             ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h);
00090 
00091                 shm_info.shmid = shmget(IPC_PRIVATE, h * ximage->bytes_per_line, IPC_CREAT | 0777);
00092                 if(shm_info.shmid < 0) perror("BC_Capture::allocate_data shmget");
00093                 data = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
00094                 shmctl(shm_info.shmid, IPC_RMID, 0);
00095                 ximage->data = shm_info.shmaddr = (char*)data;  // setting ximage->data stops BadValue
00096                 shm_info.readOnly = 0;
00097 
00098 // Crashes here if remote server.
00099                 BC_Resources::error = 0;
00100                 XShmAttach(display, &shm_info);
00101         XSync(display, False);
00102                 if(BC_Resources::error)
00103                 {
00104                         XDestroyImage(ximage);
00105                         shmdt(shm_info.shmaddr);
00106                         use_shm = 0;
00107                 }
00108         }
00109 
00110         if(!use_shm)
00111         {
00112 // need to use bytes_per_line for some X servers
00113                 data = 0;
00114                 ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
00115                 data = (unsigned char*)malloc(h * ximage->bytes_per_line);
00116                 XDestroyImage(ximage);
00117 
00118                 ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
00119         }
00120 
00121         row_data = new unsigned char*[h];
00122         for(int i = 0; i < h; i++)
00123         {
00124                 row_data[i] = &data[i * ximage->bytes_per_line];
00125         }
00126 // This differs from the depth parameter of the top_level.
00127         bits_per_pixel = ximage->bits_per_pixel;
00128         return 0;
00129 }
00130 
00131 int BC_Capture::delete_data()
00132 {
00133         if(!display) return 1;
00134         if(data)
00135         {
00136                 if(use_shm)
00137                 {
00138                         XShmDetach(display, &shm_info);
00139                         XDestroyImage(ximage);
00140                         shmdt(shm_info.shmaddr);
00141                 }
00142                 else
00143                 {
00144                         XDestroyImage(ximage);
00145                 }
00146 
00147 // data is automatically freed by XDestroyImage
00148                 data = 0;
00149                 delete row_data;
00150         }
00151         return 0;
00152 }
00153 
00154 
00155 int BC_Capture::get_w() { return w; }
00156 int BC_Capture::get_h() { return h; }
00157 
00158 // Capture a frame from the screen
00159 #define CAPTURE_FRAME_HEAD \
00160         for(int i = 0; i < h; i++) \
00161         { \
00162                 unsigned char *input_row = row_data[i]; \
00163                 unsigned char *output_row = (unsigned char*)frame->get_rows()[i]; \
00164                 for(int j = 0; j < w; j++) \
00165                 {
00166 
00167 #define CAPTURE_FRAME_TAIL \
00168                 } \
00169         }
00170 
00171 
00172 
00173 int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1)
00174 {
00175         if(!display) return 1;
00176         if(x1 < 0) x1 = 0;
00177         if(y1 < 0) y1 = 0;
00178         if(x1 > get_top_w() - w) x1 = get_top_w() - w;
00179         if(y1 > get_top_h() - h) y1 = get_top_h() - h;
00180 
00181 
00182 // Read the raw data
00183         if(use_shm)
00184                 XShmGetImage(display, rootwin, ximage, x1, y1, 0xffffffff);
00185         else
00186                 XGetSubImage(display, rootwin, x1, y1, w, h, 0xffffffff, ZPixmap, ximage, 0, 0);
00187 
00188         cmodel_transfer(frame->get_rows(), 
00189                 row_data,
00190                 frame->get_y(),
00191                 frame->get_u(),
00192                 frame->get_v(),
00193                 0,
00194                 0,
00195                 0,
00196                 0, 
00197                 0, 
00198                 w, 
00199                 h,
00200                 0, 
00201                 0, 
00202                 frame->get_w(), 
00203                 frame->get_h(),
00204                 bitmap_color_model, 
00205                 frame->get_color_model(),
00206                 0,
00207                 frame->get_w(),
00208                 w);
00209 
00210         return 0;
00211 }
00212 
00213 int BC_Capture::get_top_w()
00214 {
00215         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
00216         return WidthOfScreen(screen_ptr);
00217 }
00218 
00219 int BC_Capture::get_top_h()
00220 {
00221         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
00222         return HeightOfScreen(screen_ptr);
00223 }

Generated on Sun Jan 8 13:26:32 2006 for Guicast-svn by  doxygen 1.4.4