[asterisk-commits] rizzo: branch rizzo/video_v2 r82493 - /team/rizzo/video_v2/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Sep 16 03:45:33 CDT 2007
Author: rizzo
Date: Sun Sep 16 03:45:32 2007
New Revision: 82493
URL: http://svn.digium.com/view/asterisk?view=rev&rev=82493
Log:
Add a crude form of x11 grabber so we can fetch video from
the screen instead of a webcam.
Basically, the same thing i did 10 years ago when i was hacking on "vic"
(in fact, the source is a simplified version of the code i wrote at
the time).
The X11 grabber is not just a testing tool, as in many cases
you do need to exchange information that is on the screen.
Modified:
team/rizzo/video_v2/channels/console_video.c
Modified: team/rizzo/video_v2/channels/console_video.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/channels/console_video.c?view=diff&rev=82493&r1=82492&r2=82493
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Sun Sep 16 03:45:32 2007
@@ -69,6 +69,8 @@
/*
* Examples for video encoding are at http://www.irisa.fr/texmex/people/dufouil/ffmpegdoxy/apiexample_8c-source.html
*/
+
+#include <X11/Xlib.h>
#include <ffmpeg/avcodec.h>
#ifndef OLD_FFMPEG
@@ -111,6 +113,10 @@
struct timeval ts;
struct timeval msts;
int mtu;
+
+ struct timeval last_frame;
+ Display *dpy;
+ XImage *image;
};
struct video_in_desc {
@@ -202,7 +208,31 @@
if (v->buf.data) /* buffer allocated means device already open */
return v->fd;
-
+ /*
+ * if the device is "X11", then open the x11 grabber
+ */
+ if (!strcmp(device, "X11")) {
+ int x_ofs = 0;
+ int y_ofs = 0;
+ XImage *im;
+
+ v->dpy = XOpenDisplay(NULL);
+ ast_log(LOG_WARNING, "XOpenDisplay %pd\n", v->dpy);
+ v->image = im = XGetImage(v->dpy,
+ RootWindow(v->dpy, DefaultScreen(v->dpy)),
+ x_ofs, y_ofs, v->w, v->h, AllPlanes, ZPixmap);
+ if (v->image == NULL) {
+ ast_log(LOG_WARNING, "error creating Ximage\n");
+ XCloseDisplay(v->dpy);
+ v->image = NULL;
+ goto error;
+ }
+ ast_log(LOG_WARNING, "image: data %p %d bpp, mask 0x%lx 0x%lx 0x%lx\n",
+ im->data,
+ im->bits_per_pixel,
+ im->red_mask, im->green_mask, im->blue_mask);
+ v->fd = -2;
+ } else {
v->fd = open(device, O_RDONLY | O_NONBLOCK);
if (v->fd < 0) {
ast_log(LOG_WARNING, "error opening camera %s\n", device);
@@ -217,7 +247,6 @@
vw.width = v->w;
vw.height = v->h;
vw.flags = v->fps << 16;
- v->buf.size = (vw.width * vw.height * 3)/2; /* yuv411 */
if (ioctl(v->fd, VIDIOCSWIN, &vw) == -1) {
ast_log(LOG_WARNING, "error setting format for %s [%s]\n", device, strerror(errno));
goto error;
@@ -235,6 +264,8 @@
ast_log(LOG_WARNING, "error setting picture info\n");
goto error;
}
+ }
+ v->buf.size = (v->w * v->h * 3)/2; /* yuv411 */
ast_log(LOG_WARNING, "videodev %s opened, size %dx%d %d\n", device, v->w, v->h, v->buf.size);
v->buf.data = ast_calloc(1, v->buf.size);
if (!v->buf.data) {
@@ -264,6 +295,43 @@
if (v->buf.data == NULL) /* not initialized */
return 0;
+ if (v->image) { // X11 grabber
+ struct timeval now = ast_tvnow();
+ int td = 1000/v->fps;
+
+ /* check if it is time to read */
+ if (ast_tvzero(v->last_frame))
+ v->last_frame = now;
+ if (ast_tvdiff_ms(now, v->last_frame) < td) {
+ return 0; /* too early */
+ }
+ v->last_frame = now; /* XXX actually, should correct for drift */
+ /* read frame from X11 */
+ XGetSubImage(v->dpy,
+ RootWindow(v->dpy, DefaultScreen(v->dpy)),
+ 0, 0, v->w, v->h, AllPlanes, ZPixmap, v->image, 0, 0);
+
+ /* convert to yuv - surely ffmpeg could do ? */
+ /* this works for rgb565 */
+ {
+ int x, y;
+ int ulen = (v->h * v->w) / 4;
+ uint16_t *src = (uint16_t *)v->image->data;
+ char *dst = v->buf.data;
+ char *up = dst + ulen*4;
+ char *vp = up + ulen;
+
+ for (y = 0; y < v->h; y++) {
+ for (x = 0; x < v->w; x++) {
+ *dst++ = (*src++ & 0x7e0) >> 3;
+ }
+ }
+ memset(up, 0x80, ulen);
+ memset(vp, 0x80, ulen);
+ }
+
+ return v->buf.size; /* return the actual size */
+ }
for (;;) {
int r, l = v->buf.size - v->buf.used;
r = read(v->fd, v->buf.data + v->buf.used, l);
@@ -384,6 +452,11 @@
if (v->buf.data)
free(v->buf.data);
+ if (v->image) { /* X11 grabber */
+ XCloseDisplay(v->dpy);
+ v->dpy = NULL;
+ v->image = NULL;
+ }
if(v->fd >= 0)
close(v->fd);
@@ -442,14 +515,12 @@
v->context = NULL;
return video_out_uninit(v);
}
- fprintf(stderr, "2...");
v->frame = avcodec_alloc_frame();
if (!v->frame) {
ast_log(LOG_WARNING, "Unable to allocate the encoding video frame\n");
return video_out_uninit(v);
}
- fprintf(stderr, "3...\n");
if(!v->buf.data) {
ast_log(LOG_WARNING, "Unable to set frame buffer\n");
@@ -507,7 +578,6 @@
}*/
{ /* clear the struct but restore some fields */
struct video_desc x = *env; /* make a copy */
- fprintf(stderr, "vd: %s\n", x.videodevice);
bzero(env, sizeof(struct video_desc));
/* restore fields... */
bcopy(x.videodevice, env->videodevice, sizeof(env->videodevice));
@@ -631,15 +701,22 @@
{
AVPicture pict;
SDL_Rect rect;
- AVCodecContext *c = env->in.context; /* shorthand */
- int w = env->out.w ? env->out.w : c->width; /* pick geometry between webcam and default */
- int h = env->out.h ? env->out.h : c->height; /* pick geometry between webcam and default */
+ int w, h;
+ AVCodecContext *c; /* shorthand */
SDL_Overlay *bmp;
int fmt = SDL_YV12_OVERLAY;
fmt = SDL_IYUV_OVERLAY;
if (!env->initialized)
return;
+
+ if (out) {
+ c = env->out.context;
+ } else {
+ c = env->in.context;
+ }
+ w = env->out.w ? env->out.w : c->width; /* pick geometry between webcam and default */
+ h = env->out.h ? env->out.h : c->height; /* pick geometry between webcam and default */
#if 0
fprintf(stderr, "thd %p env->out %dx%d in.ctx %dx%d default %dx%d\n",
pthread_self(),
@@ -840,7 +917,6 @@
}
#else
uint8_t *p, *ret = NULL;
- // fprintf(stderr, "begin %p end %p\n", begin, end);
if(begin == end) return NULL;
for(p = begin; p < end-2; ++p) {
if(p[0] == 0 && p[1] == 0) {
More information about the asterisk-commits
mailing list