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