00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "asterisk.h"
00048 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 130733 $")
00049 #include <sys/ioctl.h>
00050 #include "asterisk/file.h"
00051 #include "asterisk/utils.h"
00052
00053 #include "console_video.h"
00054
00055 #if defined(HAVE_VIDEO_CONSOLE)
00056
00057 #ifdef HAVE_X11
00058
00059
00060
00061 #include <X11/Xlib.h>
00062
00063
00064 struct grab_x11_desc {
00065 Display *dpy;
00066 XImage *image;
00067 int screen_width;
00068 int screen_height;
00069 struct fbuf_t b;
00070 };
00071
00072 static void *grab_x11_close(void *desc);
00073
00074
00075
00076
00077 static void *grab_x11_open(const char *name, struct fbuf_t *geom, int fps)
00078 {
00079 XImage *im;
00080 int screen_num;
00081 struct grab_x11_desc *v;
00082 struct fbuf_t *b;
00083
00084
00085 if (strncasecmp(name, "X11", 3))
00086 return NULL;
00087 v = ast_calloc(1, sizeof(*v));
00088 if (v == NULL)
00089 return NULL;
00090
00091
00092 v->dpy = XOpenDisplay(NULL);
00093 if (v->dpy == NULL) {
00094 ast_log(LOG_WARNING, "error opening display\n");
00095 goto error;
00096 }
00097
00098 v->b = *geom;
00099 b = &v->b;
00100
00101 screen_num = DefaultScreen(v->dpy);
00102 v->screen_width = DisplayWidth(v->dpy, screen_num);
00103 v->screen_height = DisplayHeight(v->dpy, screen_num);
00104
00105 v->image = im = XGetImage(v->dpy,
00106 RootWindow(v->dpy, DefaultScreen(v->dpy)),
00107 b->x, b->y, b->w, b->h, AllPlanes, ZPixmap);
00108 if (v->image == NULL) {
00109 ast_log(LOG_WARNING, "error creating Ximage\n");
00110 goto error;
00111 }
00112 switch (im->bits_per_pixel) {
00113 case 32:
00114 b->pix_fmt = PIX_FMT_RGBA32;
00115 break;
00116 case 16:
00117 b->pix_fmt = (im->green_mask == 0x7e0) ? PIX_FMT_RGB565 : PIX_FMT_RGB555;
00118 break;
00119 }
00120
00121 ast_log(LOG_NOTICE, "image: data %p %d bpp fmt %d, mask 0x%lx 0x%lx 0x%lx\n",
00122 im->data,
00123 im->bits_per_pixel,
00124 b->pix_fmt,
00125 im->red_mask, im->green_mask, im->blue_mask);
00126
00127
00128 b->data = (uint8_t *)im->data;
00129 return v;
00130
00131 error:
00132 return grab_x11_close(v);
00133 }
00134
00135 static struct fbuf_t *grab_x11_read(void *desc)
00136 {
00137
00138 struct grab_x11_desc *v = desc;
00139 struct fbuf_t *b = &v->b;
00140
00141 XGetSubImage(v->dpy,
00142 RootWindow(v->dpy, DefaultScreen(v->dpy)),
00143 b->x, b->y, b->w, b->h, AllPlanes, ZPixmap, v->image, 0, 0);
00144
00145 b->data = (uint8_t *)v->image->data;
00146 return b;
00147 }
00148
00149 static int boundary_checks(int x, int limit)
00150 {
00151 return (x <= 0) ? 0 : (x > limit ? limit : x);
00152 }
00153
00154
00155
00156
00157 static void grab_x11_move(void *desc, int dx, int dy)
00158 {
00159 struct grab_x11_desc *v = desc;
00160
00161 v->b.x = boundary_checks(v->b.x + dx, v->screen_width - v->b.w);
00162 v->b.y = boundary_checks(v->b.y + dy, v->screen_height - v->b.h);
00163 }
00164
00165
00166 static void *grab_x11_close(void *desc)
00167 {
00168 struct grab_x11_desc *v = desc;
00169
00170 if (v->dpy)
00171 XCloseDisplay(v->dpy);
00172 v->dpy = NULL;
00173 v->image = NULL;
00174 ast_free(v);
00175 return NULL;
00176 }
00177
00178 static struct grab_desc grab_x11_desc = {
00179 .name = "X11",
00180 .open = grab_x11_open,
00181 .read = grab_x11_read,
00182 .move = grab_x11_move,
00183 .close = grab_x11_close,
00184 };
00185 #endif
00186
00187 #ifdef HAVE_VIDEODEV_H
00188 #include <linux/videodev.h>
00189
00190 struct grab_v4l1_desc {
00191 int fd;
00192 struct fbuf_t b;
00193 };
00194
00195
00196
00197
00198
00199 static void *grab_v4l1_open(const char *dev, struct fbuf_t *geom, int fps)
00200 {
00201 struct video_window vw = { 0 };
00202 struct video_picture vp;
00203 int fd, i;
00204 struct grab_v4l1_desc *v;
00205 struct fbuf_t *b;
00206
00207
00208 if (strncmp(dev, "/dev/", 5))
00209 return NULL;
00210 fd = open(dev, O_RDONLY | O_NONBLOCK);
00211 if (fd < 0) {
00212 ast_log(LOG_WARNING, "error opening camera %s\n", dev);
00213 return NULL;
00214 }
00215
00216 v = ast_calloc(1, sizeof(*v));
00217 if (v == NULL) {
00218 ast_log(LOG_WARNING, "no memory for camera %s\n", dev);
00219 close(fd);
00220 return NULL;
00221 }
00222 v->fd = fd;
00223 v->b = *geom;
00224 b = &v->b;
00225
00226 i = fcntl(fd, F_GETFL);
00227 if (-1 == fcntl(fd, F_SETFL, i | O_NONBLOCK)) {
00228
00229 ast_log(LOG_WARNING, "error F_SETFL for %s [%s]\n",
00230 dev, strerror(errno));
00231 }
00232
00233
00234
00235
00236 vw.width = b->w;
00237 vw.height = b->h;
00238 vw.flags = fps << 16;
00239 if (ioctl(fd, VIDIOCSWIN, &vw) == -1) {
00240 ast_log(LOG_WARNING, "error setting format for %s [%s]\n",
00241 dev, strerror(errno));
00242 goto error;
00243 }
00244 if (ioctl(fd, VIDIOCGPICT, &vp) == -1) {
00245 ast_log(LOG_WARNING, "error reading picture info\n");
00246 goto error;
00247 }
00248 ast_log(LOG_WARNING,
00249 "contrast %d bright %d colour %d hue %d white %d palette %d\n",
00250 vp.contrast, vp.brightness,
00251 vp.colour, vp.hue,
00252 vp.whiteness, vp.palette);
00253
00254
00255
00256
00257 b->pix_fmt = vp.palette;
00258 vp.palette = VIDEO_PALETTE_YUV420P;
00259 if (ioctl(v->fd, VIDIOCSPICT, &vp) == -1) {
00260 ast_log(LOG_WARNING, "error setting palette, using %d\n",
00261 b->pix_fmt);
00262 } else
00263 b->pix_fmt = vp.palette;
00264
00265
00266
00267
00268 b->size = (b->w * b->h * 3)/2;
00269 ast_log(LOG_WARNING, "videodev %s opened, size %dx%d %d\n",
00270 dev, b->w, b->h, b->size);
00271 b->data = ast_calloc(1, b->size);
00272 if (!b->data) {
00273 ast_log(LOG_WARNING, "error allocating buffer %d bytes\n",
00274 b->size);
00275 goto error;
00276 }
00277 ast_log(LOG_WARNING, "success opening camera\n");
00278 return v;
00279
00280 error:
00281 close(v->fd);
00282 fbuf_free(b);
00283 ast_free(v);
00284 return NULL;
00285 }
00286
00287
00288
00289
00290
00291 static struct fbuf_t *grab_v4l1_read(void *desc)
00292 {
00293 struct grab_v4l1_desc *v = desc;
00294 struct fbuf_t *b = &v->b;
00295 for (;;) {
00296 int r, l = b->size - b->used;
00297 r = read(v->fd, b->data + b->used, l);
00298
00299 if (r < 0)
00300 break;
00301 if (r == 0)
00302 break;
00303 b->used += r;
00304 if (r == l) {
00305 b->used = 0;
00306 return b;
00307 }
00308 }
00309 return NULL;
00310 }
00311
00312 static void *grab_v4l1_close(void *desc)
00313 {
00314 struct grab_v4l1_desc *v = desc;
00315
00316 close(v->fd);
00317 v->fd = -1;
00318 fbuf_free(&v->b);
00319 ast_free(v);
00320 return NULL;
00321 }
00322
00323
00324 static struct grab_desc grab_v4l1_desc = {
00325 .name = "v4l1",
00326 .open = grab_v4l1_open,
00327 .read = grab_v4l1_read,
00328 .close = grab_v4l1_close,
00329 };
00330 #endif
00331
00332
00333
00334
00335
00336
00337
00338 struct grab_desc *console_grabbers[] = {
00339 #ifdef HAVE_X11
00340 &grab_x11_desc,
00341 #endif
00342 #ifdef HAVE_VIDEODEV_H
00343 &grab_v4l1_desc,
00344 #endif
00345 NULL
00346 };
00347
00348 #endif