Here is a somewhat detailed explanation of how xcaptest works. You are correct, he has a global set of XImages, declared like thus... XImage *capt_ximg[STREAMBUFS]; He also has a struct that has everything he wants to know about the capture buffers and the capture device itself, declared like thus typedef struct { int fd_video; int width; int height; int depth; int pixelformat; VIMAGE vimage[STREAMBUFS]; struct v4l2_format fmt; struct v4l2_requestbuffers req; }capture_device; Pay attention to how he initializes the vimage member of that struct, it ends up containing pointers to the mmap'ed memory used for streaming capture. pcapt_d->vimage[i].data = mmap (0, vidbuf->length, PROT_READ|PROT_WRITE, MAP_PRIVATE/*MAP_SHARED*/, pcapt_d->fd_video, vidbuf->offset); if ((int) pcapt_d->vimage[i].data == -1) { perror ("mmap() in capture_start"); return 0; } pcapt_d->vimage[i].length = vidbuf->length; Later on, he passes in the memory FROM THE VIMAGE MEMBER to the call to XCreateImage, at the same time setting the data member of each member of his global set of XImages to the memory fmmap'ed rom the capture card. capt_ximg[i] = display_alloc (pcapt_w, pcapt_d->vimage[i].data, pcapt_d->width, pcapt_d->height); That is why you seem to see the capture device capture directly to his ximage array. Here are several a bugfixes of the xcapture program (I don't know who to submit them too). It still does not work, but at least it gets a lot further than failing at the mmap section First off, open a video capture device you want to use for streaming like thus, else the mmap later fails: open (my_device, O_RDWR); NOT open (my_device, O_RDONLY); Second off, when you mmap, do it like this mmap (0, vidbuf->length, PROT_READ|PROT_WRITE, MAP_SHARED, pcapt_d->fd_video, vidbuf->offset); NOT like this: mmap (0, vidbuf->length, PROT_READ|PROT_WRITE, MAP_PRIVATE, pcapt_d->fd_video, vidbuf->offset); else you get an EACCES error. Check out what happens when he wants to exit, specifically to his set of XImages: void display_free (XImage *XImgTmp) { if (XImgTmp) // memory leak, but XDestroyImage always segfaults... // XDestroyImage(XImgTmp); return; } What is happening here is that XDestroyImage is attempting to free the data member of the XImage struct, but that member is set to the memory from the capture card, thus the free causes a segfault. A non-leaking (in this case), non-segfaulting version would look like thus: void display_free (XImage *XImgTmp) { if (XImgTmp) { XImgTmp->data = NULL; XDestroyImage(XImgTmp); } return; } Hope this helps, Chris