[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