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
00016
00017
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
00074
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
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;
00096 shm_info.readOnly = 0;
00097
00098
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
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
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
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
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
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 }