--- libavformat/x11grab.c 2006-12-13 00:45:16.000000000 +0100 +++ libavformat/x11grab.c 2006-12-13 00:55:24.000000000 +0100 @@ -361,122 +361,156 @@ } -/* - * just read new data in the image structure, the image - * structure inclusive the data area must be allocated before +/** + * Reads new data in the image structure. + * + * @param dpy X11 display to grab from + * @param d + * @param image Image where the grab will be put + * @param x Top-Left grabbing rectangle horizontal coordinate + * @param y Top-Left grabbing rectangle vertical coordinate + * @return 0 if error, !0 if successful */ static int -XGetZPixmap(Display *dpy, Drawable d, XImage *image, int x, int y) +xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y) { - xGetImageReply rep; - xGetImageReq *req; - long nbytes; - - if (!image) - return (False); - LockDisplay(dpy); - GetReq(GetImage, req); - /* - * first set up the standard stuff in the request - */ - req->drawable = d; - req->x = x; - req->y = y; - req->width = image->width; - req->height = image->height; - req->planeMask = AllPlanes; - req->format = ZPixmap; - - if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0 || - rep.length == 0) { + xGetImageReply rep; + xGetImageReq *req; + long nbytes; + + if (!image) { + return 0; + } + + LockDisplay(dpy); + GetReq(GetImage, req); + + /* First set up the standard stuff in the request */ + req->drawable = d; + req->x = x; + req->y = y; + req->width = image->width; + req->height = image->height; + req->planeMask = (unsigned int)AllPlanes; + req->format = ZPixmap; + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) { + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + nbytes = (long)rep.length << 2; + _XReadPad(dpy, image->data, nbytes); + UnlockDisplay(dpy); SyncHandle(); - return (False); - } - - nbytes = (long)rep.length << 2; - _XReadPad(dpy, image->data, nbytes); - - UnlockDisplay(dpy); - SyncHandle(); - return (True); + return 1; } +/** + * Grabs a frame from x11 (public device demuxer API). + * + * @param s1 Context from avformat core + * @param pkt Packet holding the brabbed frame + * @return frame size in bytes + */ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) { - X11Grab *s = s1->priv_data; - Display *dpy = s->dpy; - XImage *image = s->image; - int x_off = s->x_off; - int y_off = s->y_off; - - int64_t curtime, delay; - struct timespec ts; - - /* Calculate the time of the next frame */ - s->time_frame += int64_t_C(1000000); - - /* wait based on the frame rate */ - for(;;) { - curtime = av_gettime(); - delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime; - if (delay <= 0) { - if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) { - /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */ - s->time_frame += int64_t_C(1000000); - } - break; - } - ts.tv_sec = delay / 1000000; - ts.tv_nsec = (delay % 1000000) * 1000; - nanosleep(&ts, NULL); - } - - if (av_new_packet(pkt, s->frame_size) < 0) - return AVERROR_IO; - - pkt->pts = curtime & ((1LL << 48) - 1); - - if(s->use_shm) { - if (!XShmGetImage(dpy, - RootWindow(dpy, DefaultScreen(dpy)), - image, x_off, y_off, AllPlanes)) { - fprintf(stderr,"XShmGetImage() failed\n"); - } - } - else { - XGetZPixmap(dpy, - RootWindow(dpy, DefaultScreen(dpy)), - image, x_off, y_off); - }; - { - int pointer_x, pointer_y; - getCurrentPointer(s, &pointer_x, &pointer_y); - paintMousePointer(s, &pointer_x, &pointer_y, image); - } - -#warning FIXME - avoid memcpy - memcpy(pkt->data, image->data, s->frame_size); - return s->frame_size; + x11_grab_t *s = s1->priv_data; + Display *dpy = s->dpy; + XImage *image = s->image; + int x_off = s->x_off; + int y_off = s->y_off; + + int64_t curtime, delay; + struct timespec ts; + + /* Calculate the time of the next frame */ + s->time_frame += int64_t_C(1000000); + + /* wait based on the frame rate */ + for(;;) { + curtime = av_gettime(); + delay = s->time_frame * av_q2d(s->time_base) - curtime; + if (delay <= 0) { + if (delay < int64_t_C(-1000000) * av_q2d(s->time_base)) { + s->time_frame += int64_t_C(1000000); + } + break; + } + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL); + } + + if (av_new_packet(pkt, s->frame_size) < 0) { + return AVERROR_IO; + } + + pkt->pts = curtime; + + if(s->use_shm) { + if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { + av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); + } + } else { + if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { + av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); + } + } + + { + int pointer_x, pointer_y; + get_pointer_coordinates(&pointer_x, &pointer_y, dpy, s1); + paint_mouse_pointer(image, s, pointer_x, pointer_y); + } + + + /* XXX: avoid memcpy */ + memcpy(pkt->data, image->data, s->frame_size); + return s->frame_size; } +/** + * Closes x11 frame grabber (public device demuxer API). + * + * @param s1 Context from avformat core + * @return 0 success, !0 failure + */ static int x11grab_read_close(AVFormatContext *s1) { - X11Grab *x11grab = s1->priv_data; - - XCloseDisplay(x11grab->dpy); - return 0; + x11_grab_t *x11grab = s1->priv_data; + + /* Detach cleanly from shared mem */ + if (x11grab->use_shm) { + XShmDetach(x11grab->dpy, &x11grab->shminfo); + shmdt(x11grab->shminfo.shmaddr); + shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); + } + + /* Destroy X11 image */ + if (x11grab->image) { + XDestroyImage(x11grab->image); + x11grab->image = NULL; + } + + /* Free X11 display */ + XCloseDisplay(x11grab->dpy); + return 0; } -AVInputFormat x11_grab_device_demuxer = { - "x11grab", - "X11grab", - sizeof(X11Grab), - NULL, - x11grab_read_header, - x11grab_read_packet, - x11grab_read_close, - .flags = AVFMT_NOFILE, +/** x11 grabber device demuxer declaration */ +AVInputFormat x11_grab_device_demuxer = +{ + "x11grab", + "X11grab", + sizeof(x11_grab_t), + NULL, + x11grab_read_header, + x11grab_read_packet, + x11grab_read_close, + .flags = AVFMT_NOFILE, };