Beispiel #1
0
BC_XvShmImage::BC_XvShmImage(BC_Bitmap *bitmap, int index,
	int w, int h, int color_model)
 : BC_BitmapImage(bitmap, index)
{
	Display *display = top_level->get_display();
	int id = BC_CModels::bc_to_x(color_model);
// Create the XvImage
	xv_image = XvShmCreateImage(display, bitmap->xv_portid, id,
			0, w, h, &shm_info);
	dataSize = xv_image->data_size;
// Create the shared memory
	shm_info.shmid = shmget(IPC_PRIVATE, 
		dataSize + 8, IPC_CREAT | 0777);
	if(shm_info.shmid < 0)
		perror("BC_XvShmImage::BC_XvShmImage shmget");
	data = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
// This causes it to automatically delete when the program exits.
	shmctl(shm_info.shmid, IPC_RMID, 0);
// setting ximage->data stops BadValue
	xv_image->data = shm_info.shmaddr = (char*)data;
	shm_info.readOnly = 0;
// Get the real parameters
	w = xv_image->width;
	h = xv_image->height;
	if(!XShmAttach(top_level->display, &shm_info))
		perror("BC_XvShmImage::BC_XvShmImage XShmAttach");
	if( color_model == BC_YUV422 ) {
	 	bytesPerLine = w*2;
		bitsPerPixel = 12;
		row_data = new unsigned char*[h];
		for( int i=0; i<h; ++i )
			row_data[i] = &data[i*bytesPerLine];
	}
}
Beispiel #2
0
static int xv_alloc_frame( void )
{
    int size;
    uint8_t *alloc;

    size = input_width * input_height * 2;
    if( use_shm ) {
        alloc = create_shm( size );
    } else {
        alloc = malloc( input_width * input_height * 2 );
    }

    if( alloc ) {
        /* Initialize the input image to black. */
        blit_colour_packed422_scanline( alloc, input_width * input_height,
                                        16, 128, 128 );
        if( use_shm ) {
            image = XvShmCreateImage( display, xv_port, FOURCC_YUY2,
                                      (char *) alloc, input_width,
                                      input_height, &shminfo );
        } else {
            image = XvCreateImage( display, xv_port, FOURCC_YUY2,
                                   (char *) alloc, input_width,
                                   input_height );
        }
        image_data = alloc;
        return 1;
    }

    return 0;
}
Beispiel #3
0
    bool prepareImage(int w, int h) {
        if (xv_image_width == w && xv_image_height == h && xv_image)
            return true;
        xv_image_width = w;
        xv_image_height = h;
#ifdef _XSHM_H_
        if (use_shm) {
            xv_image = XvShmCreateImage(display, xv_port, format_id, 0, xv_image_width, xv_image_height, &shm);
            shm.shmid = shmget(IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
            if (shm.shmid < 0) {
                qCritical("get shm failed. try to use none shm");
                use_shm = false;
            } else {
                shm.shmaddr = (char *)shmat(shm.shmid, 0, 0);
                xv_image->data = shm.shmaddr;
                shm.readOnly = 0;
                if (XShmAttach(display, &shm)) {
                    XSync(display, false);
                    shmctl(shm.shmid, IPC_RMID, 0);
                } else {
                    qCritical("Attach to shm failed! try to use none shm");
                    use_shm = false;
                }
            }
        }
#endif //_XSHM_H_
        if (!use_shm) {
            xv_image = XvCreateImage(display, xv_port, format_id, 0, xv_image_width, xv_image_height);
            // malloc if use copy (e.g. shm)
            xv_image->data = (char*)malloc(xv_image->data_size);
        }
        return true;
    }
Beispiel #4
0
XvImage* create_yuv_image(Display* display, XvPortID port, fourcc_t format,
			  int width, int height, XShmSegmentInfo* shminfo)
{
  XvImage* image;

  if (shminfo) {
    if (!(image = XvShmCreateImage(display, port, format.id, NULL,
				   width, height, shminfo)))
    {
      printf("Unable to create shm XvImage\n");
      return NULL;
    }
      
    if ((shminfo->shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777)) == -1)
    {
      printf("Unable to allocate shared memory\n");
      XFree(image);
      return NULL;
    }
    if (!(shminfo->shmaddr = shmat(shminfo->shmid, 0, 0))) {
      printf("Unable to attach shared memory\n");
      XFree(image);
      shmctl(shminfo->shmid, IPC_RMID, 0);
      return NULL;
    }
    shminfo->readOnly = False;

    image->data = shminfo->shmaddr;

    if (!XShmAttach(display, shminfo)) {
      printf("XShmAttach failed\n");
      XFree(image);
      shmctl(shminfo->shmid, IPC_RMID, 0);
      shmdt(shminfo->shmaddr);
      return NULL;
    }

    /* Send image to X server. This instruction is required, since having
     * built a Shm XImage and not using it causes an error on XCloseDisplay. */
    XSync(display, False);

    /* Mark the segment to be automatically removed when the last
       attachment is broken (i.e. on shmdt or process exit). */
    shmctl(shminfo->shmid, IPC_RMID, 0);
  }
  else {
    if (!(image = XvCreateImage(display, port, format.id, NULL,
				width, height)))
    {
      printf("Unable to create XvImage\n");
      return NULL;
    }
    image->data = malloc(image->data_size);
  }

  return image;
}
Beispiel #5
0
static bool allocate_xvimage(struct vo *vo, int foo)
{
    struct xvctx *ctx = vo->priv;
    struct vo_x11_state *x11 = vo->x11;
    // align it for faster OSD rendering (draw_bmp.c swscale usage)
    int aligned_w = FFALIGN(ctx->image_width, 32);
#if HAVE_SHM
    if (x11->display_is_local && XShmQueryExtension(x11->display)) {
        ctx->Shmem_Flag = 1;
        x11->ShmCompletionEvent = XShmGetEventBase(x11->display)
                                + ShmCompletion;
    } else {
        ctx->Shmem_Flag = 0;
        MP_INFO(vo, "Shared memory not supported\nReverting to normal Xv.\n");
    }
    if (ctx->Shmem_Flag) {
        ctx->xvimage[foo] =
            (XvImage *) XvShmCreateImage(x11->display, ctx->xv_port,
                                         ctx->xv_format, NULL,
                                         aligned_w, ctx->image_height,
                                         &ctx->Shminfo[foo]);
        if (!ctx->xvimage[foo])
            return false;

        ctx->Shminfo[foo].shmid = shmget(IPC_PRIVATE,
                                         ctx->xvimage[foo]->data_size,
                                         IPC_CREAT | 0777);
        ctx->Shminfo[foo].shmaddr = (char *) shmat(ctx->Shminfo[foo].shmid, 0,
                                                   0);
        if (ctx->Shminfo[foo].shmaddr == (void *)-1)
            return false;
        ctx->Shminfo[foo].readOnly = False;

        ctx->xvimage[foo]->data = ctx->Shminfo[foo].shmaddr;
        XShmAttach(x11->display, &ctx->Shminfo[foo]);
        XSync(x11->display, False);
        shmctl(ctx->Shminfo[foo].shmid, IPC_RMID, 0);
    } else
#endif
    {
        ctx->xvimage[foo] =
            (XvImage *) XvCreateImage(x11->display, ctx->xv_port,
                                      ctx->xv_format, NULL, aligned_w,
                                      ctx->image_height);
        if (!ctx->xvimage[foo])
            return false;
        ctx->xvimage[foo]->data = av_malloc(ctx->xvimage[foo]->data_size);
        if (!ctx->xvimage[foo]->data)
            return false;
        XSync(x11->display, False);
    }
    struct mp_image img = get_xv_buffer(vo, foo);
    img.w = aligned_w;
    mp_image_clear(&img, 0, 0, img.w, img.h);
    return true;
}
void QGstXvImageBufferPool::doAlloc()
{
    //should be always called from the main thread with m_poolMutex locked
    //Q_ASSERT(QThread::currentThread() == thread());

    XSync(QX11Info::display(), false);

    QGstXvImageBuffer *xvBuffer = (QGstXvImageBuffer *)gst_mini_object_new(QGstXvImageBuffer::get_type());

    quint64 portId = m_format.property("portId").toULongLong();
    int xvFormatId = m_format.property("xvFormatId").toInt();

    xvBuffer->xvImage = XvShmCreateImage(
            QX11Info::display(),
            portId,
            xvFormatId,
            0,
            m_format.frameWidth(),
            m_format.frameHeight(),
            &xvBuffer->shmInfo
            );

    if (!xvBuffer->xvImage) {
        qWarning() << "QGstXvImageBufferPool: XvShmCreateImage failed";
        return;
    }

    XSync(QX11Info::display(), false);

    xvBuffer->shmInfo.shmid = shmget(IPC_PRIVATE, xvBuffer->xvImage->data_size, IPC_CREAT | 0777);
    xvBuffer->shmInfo.shmaddr = xvBuffer->xvImage->data = (char*)shmat(xvBuffer->shmInfo.shmid, 0, 0);
    xvBuffer->shmInfo.readOnly = False;

    if (!XShmAttach(QX11Info::display(), &xvBuffer->shmInfo)) {
        qWarning() << "QGstXvImageBufferPool: XShmAttach failed";
        return;
    }

    XSync(QX11Info::display(), false);

    shmctl (xvBuffer->shmInfo.shmid, IPC_RMID, NULL);

    xvBuffer->pool = this;
    GST_MINI_OBJECT_CAST(xvBuffer)->flags = 0;
    gst_buffer_set_caps(GST_BUFFER_CAST(xvBuffer), m_caps);
    GST_BUFFER_DATA(xvBuffer) = (uchar*)xvBuffer->xvImage->data;
    GST_BUFFER_SIZE(xvBuffer) = xvBuffer->xvImage->data_size;

    m_allBuffers.append(xvBuffer);
    m_pool.append(xvBuffer);

    XSync(QX11Info::display(), false);
}
void
S9xXVDisplayDriver::update_image_size (int width, int height)
{
    if (desired_width != width || desired_height != height)
    {
        XShmDetach (display, &shm);
        XSync (display, 0);

        shmctl (shm.shmid, IPC_RMID, 0);
        shmdt (shm.shmaddr);

        xv_image = XvShmCreateImage (display,
                                     xv_portid,
                                     format,
                                     0,
                                     width,
                                     height,
                                     &shm);

        shm.shmid = shmget (IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
        for (int tries = 0; tries <= 10; tries++)
        {
            shm.shmaddr = (char *) shmat (shm.shmid, 0, 0);

            if (shm.shmaddr == (void *) -1 && tries >= 10)
            {
                /* Can't recover, send exit. */
                fprintf (stderr, "Couldn't reallocate shared memory.\n");
                S9xExit ();
            }
            else if (shm.shmaddr != (void *) -1)
            {
                break;
            }
        }

        shm.readOnly = FALSE;

        xv_image->data = shm.shmaddr;

        XShmAttach (display, &shm);

        desired_width = width;
        desired_height = height;
    }

    return;
}
Beispiel #8
0
int XVWindow::init(Display* dp, Window rootWindow, int x, int y, int windowWidth, int windowHeight, int imageWidth, int imageHeight) {

	// local variables needed for creation of window and initialization of XV extension
	unsigned int i;
	unsigned int ver, rel, req, ev, err, adapt;
	XSetWindowAttributes xswattributes;
	XWindowAttributes xwattributes;
	XVisualInfo xvinfo;
	XvAdaptorInfo *xvainfo;
	unsigned int candidateXVPort=0;
	unsigned int busyPorts=0;

	_display=dp;
	_rootWindow=rootWindow;
	_state.origLayer=0;

	// initialize atoms
	WM_DELETE_WINDOW = XInternAtom(_display, "WM_DELETE_WINDOW", False);
	XA_WIN_PROTOCOLS = XInternAtom(_display, "_WIN_PROTOCOLS", False);
	XA_NET_SUPPORTED = XInternAtom(_display, "_NET_SUPPORTED", False);
	XA_NET_WM_STATE = XInternAtom(_display, "_NET_WM_STATE", False);
	XA_NET_WM_STATE_FULLSCREEN = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", False);
	XA_NET_WM_STATE_ABOVE = XInternAtom(_display, "_NET_WM_STATE_ABOVE", False);
	XA_NET_WM_STATE_STAYS_ON_TOP = XInternAtom(_display, "_NET_WM_STATE_STAYS_ON_TOP", False);
	XA_NET_WM_STATE_BELOW = XInternAtom(_display, "_NET_WM_STATE_BELOW", False);

	XGetWindowAttributes(_display, _rootWindow, &xwattributes);
	XMatchVisualInfo(_display, DefaultScreen(_display), xwattributes.depth, TrueColor, &xvinfo);

	// define window properties and create the window
	xswattributes.colormap = XCreateColormap(_display, _rootWindow, xvinfo.visual, AllocNone);
	xswattributes.event_mask = StructureNotifyMask | ExposureMask;
	xswattributes.background_pixel = 0;
	xswattributes.border_pixel = 0;
	_XVWindow = XCreateWindow(_display, _rootWindow, x, y, windowWidth, windowHeight, 0, xvinfo.depth,
	 	InputOutput, xvinfo.visual, CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &xswattributes);

	// define inputs events
	XSelectInput(_display, _XVWindow, StructureNotifyMask | KeyPressMask | ButtonPressMask);

	setSizeHints(DEFAULT_X,DEFAULT_Y, imageWidth, imageHeight, windowWidth, windowHeight);

	// map the window
	XMapWindow(_display, _XVWindow);

	XSetWMProtocols(_display, _XVWindow, &WM_DELETE_WINDOW,1);

	// check if SHM XV window is possible
	if (Success != XvQueryExtension(_display, &ver, &rel, &req, &ev, &err)) {
		LOG_DEBUG("[x11] XQueryExtension failed");
		return 0;
	}
	if (!XShmQueryExtension(_display)) {
		LOG_DEBUG("[x11] XQueryShmExtension failed");
		return 0;
	}
	if (Success != XvQueryAdaptors(_display, _rootWindow, &adapt, &xvainfo)) {
		LOG_DEBUG("[x11] XQueryAdaptor failed"); XFree(xvainfo);
		return 0;
	}

	// look for a usable XV port
	for (i = 0; i < adapt && _XVPort == 0; i++) {
		if ((xvainfo[i].type & XvInputMask) && (xvainfo[i].type & XvImageMask)) {
			for (candidateXVPort = xvainfo[i].base_id; candidateXVPort < xvainfo[i].base_id + xvainfo[i].num_ports; ++candidateXVPort)
				if (!XvGrabPort(_display, candidateXVPort, CurrentTime)) {
					_XVPort = candidateXVPort;
					break;
				} else {
					LOG_DEBUG("[x11] Could not grab port: " + String::fromNumber(candidateXVPort));
					++busyPorts;
				}
		}
	}
	XvFreeAdaptorInfo(xvainfo);

	if (!_XVPort) {
		if (busyPorts) {
			LOG_WARN("[x11] Could not find free Xvideo port - maybe another process is already using it.");
		} else {
			LOG_WARN("[x11] It seems there is no Xvideo support for your video card available.");
		}
		return 0;
	} else {
		LOG_WARN("[x11] Use XVideo port: " + String::fromNumber(_XVPort));
	}

	_gc = XCreateGC(_display, _XVWindow, 0, 0);

	// create the shared memory portion
	_XVImage = XvShmCreateImage(_display, _XVPort, GUID_I420_PLANAR, 0, imageWidth, imageHeight, &_XShmInfo);

	_XShmInfo.shmid = shmget(IPC_PRIVATE, _XVImage->data_size, IPC_CREAT | 0777);
	_XShmInfo.shmaddr = (char *) shmat(_XShmInfo.shmid, 0, 0);
	_XVImage->data = _XShmInfo.shmaddr;
	_XShmInfo.readOnly = False;
	if (!XShmAttach(_display, &_XShmInfo)) {
		LOG_WARN("[x11] XShmAttach failed");
		return 0;
	} else {
		_isInitialized = true;
	}

	// detect the window manager type
	_wmType=getWMType();

	return 1;
}
static void x11video_prepare(MSFilter *f){
	X11Video *s=(X11Video*)f->data;
	unsigned int n;
	unsigned int nadaptors;
	int i;
	XvAdaptorInfo *xai=NULL;
	XvPortID port=-1;
	int imgfmt_id=0;
	XShmSegmentInfo *shminfo=&s->shminfo;
	XWindowAttributes wa = {0};

	if (s->display==NULL) return;
	if (s->window_id==0){
		if(s->auto_window) {
			s->window_id=createX11Window(s);
		}
		if (s->window_id==0) return;
		s->own_window=TRUE;
	}

	/* Make sure X11 window is ready to use*/
	XSync(s->display, False);

	if (s->own_window==FALSE){
		/*we need to register for resize events*/
		XSelectInput(s->display,s->window_id,StructureNotifyMask);
	}
	XGetWindowAttributes(s->display,s->window_id,&wa);
	XClearWindow(s->display,s->window_id);
	ms_message("x11video_prepare(): Window has size %ix%i, received video is %ix%i",wa.width,wa.height,s->vsize.width,s->vsize.height);

	if (wa.width<MS_LAYOUT_MIN_SIZE || wa.height<MS_LAYOUT_MIN_SIZE){
		return;
	}

	s->wsize.width=wa.width;
	s->wsize.height=wa.height;
	s->fbuf.w=s->vsize.width;
	s->fbuf.h=s->vsize.height;

	s->port=-1;
	if (XvQueryExtension(s->display, &n, &n, &n, &n, &n)!=0){
		ms_error("Fail to query xv extension");
		return;
	}

	if (XShmQueryExtension(s->display)==0){
		ms_error("Fail to query xshm extension");
		return;
	}

	if (XvQueryAdaptors(s->display,DefaultRootWindow(s->display),
	                                 &nadaptors, &xai)!=0){
		ms_error("XvQueryAdaptors failed.");
		return;
	}

	for (n=0;n<nadaptors && port==-1;++n){
		XvAdaptorInfo *ai=&xai[n];
		XvImageFormatValues *imgfmt;
		int nimgfmt=0;

		ms_message("Found output adaptor; name=%s num_ports=%i, with %i formats:",
		           ai->name,(int)ai->num_ports,(int)ai->num_formats);
		imgfmt=XvListImageFormats(s->display,ai->base_id,&nimgfmt);
		for(i=0;i<nimgfmt;++i){
			char fcc[5]={0};
			memcpy(fcc,&imgfmt[i].id,4);
			ms_message("type=%s/%s id=%s",
			           imgfmt[i].type == XvYUV ? "YUV" : "RGB",
			            imgfmt[i].format==XvPlanar ? "Planar" : "Packed",fcc);
			if (port==-1 && imgfmt[i].format==XvPlanar && strcasecmp(fcc,"YV12")==0){
				int k;
				/*we found a format interesting to us*/
				for(k=0;k<ai->num_ports;++k){
					if (XvGrabPort(s->display,ai->base_id+k,CurrentTime)==0){
						ms_message("Grabbed port %i",(int)ai->base_id+k);
						port=ai->base_id+k;
						imgfmt_id=imgfmt[i].id;
						break;
					}
				}
			}
		}
		if (imgfmt) XFree(imgfmt);
	}
	XvFreeAdaptorInfo(xai);
	if (port==-1){
		ms_error("Could not find suitable format or Xv port to work with.");
		return;
	}
	s->port=port;

	/*create the shared memory XvImage*/
	memset(shminfo,0,sizeof(*shminfo));
	s->xv_image=XvShmCreateImage(s->display,s->port,imgfmt_id,NULL,s->fbuf.w,s->fbuf.h,shminfo);
	if (s->xv_image==NULL){
		ms_error("XvShmCreateImage failed.");
		x11video_unprepare(f);
		return;
	}
	/*allocate some shared memory to receive the pixel data */
	shminfo->shmid=shmget(IPC_PRIVATE, s->xv_image->data_size,IPC_CREAT | 0777);
	if (shminfo->shmid==-1){
		ms_error("Could not allocate %i bytes of shared memory: %s",
		         s->xv_image->data_size,
		         strerror(errno));
		x11video_unprepare(f);
		return;
	}
	shminfo->shmaddr=shmat(shminfo->shmid,NULL,0);
	if (shminfo->shmaddr==(void*)-1){
		ms_error("shmat() failed: %s",strerror(errno));
		shminfo->shmaddr=NULL;
		x11video_unprepare(f);
		return;
	}
	/*ask the x-server to attach this shared memory segment*/
	x11_error=FALSE;
	if (!XShmAttach(s->display,shminfo)){
		ms_error("XShmAttach failed !");
		x11video_unprepare(f);
		return ;
	}
	s->xv_image->data=s->shminfo.shmaddr;
	s->fbuf.planes[0]=(void*)s->xv_image->data;
	s->fbuf.planes[2]=s->fbuf.planes[0]+(s->xv_image->height*s->xv_image->pitches[0]);
	s->fbuf.planes[1]=s->fbuf.planes[2]+((s->xv_image->height/2)*s->xv_image->pitches[1]);
	s->fbuf.strides[0]=s->xv_image->pitches[0];
	s->fbuf.strides[2]=s->xv_image->pitches[1];
	s->fbuf.strides[1]=s->xv_image->pitches[2];

	/* set picture black */
	x11video_fill_background(f);

	/*Create a GC*/
	s->gc=XCreateGC(s->display,s->window_id,0,NULL);
	if (s->gc==NULL){
		ms_error("XCreateGC() failed.");
		x11video_unprepare(f);
		return ;
	}

	s->ready=TRUE;
}
Beispiel #10
0
static GstXvImageMeta *
gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
{
  GstXvImageSink *xvimagesink;
  int (*handler) (Display *, XErrorEvent *);
  gboolean success = FALSE;
  GstXContext *xcontext;
  GstXvImageMeta *meta;
  gint width, height, im_format, align = 15, offset;
  GstXvImageBufferPoolPrivate *priv;

  priv = xvpool->priv;
  xvimagesink = xvpool->sink;
  xcontext = xvimagesink->xcontext;

  width = priv->padded_width;
  height = priv->padded_height;
  im_format = priv->im_format;

  meta =
      (GstXvImageMeta *) gst_buffer_add_meta (buffer, GST_XVIMAGE_META_INFO,
      NULL);
#ifdef HAVE_XSHM
  meta->SHMInfo.shmaddr = ((void *) -1);
  meta->SHMInfo.shmid = -1;
#endif
  meta->x = priv->align.padding_left;
  meta->y = priv->align.padding_top;
  meta->width = priv->info.width;
  meta->height = priv->info.height;
  meta->sink = gst_object_ref (xvimagesink);
  meta->im_format = im_format;

  GST_DEBUG_OBJECT (xvimagesink, "creating image %p (%dx%d)", buffer,
      width, height);

  g_mutex_lock (&xvimagesink->x_lock);

  /* Setting an error handler to catch failure */
  error_caught = FALSE;
  handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);

#ifdef HAVE_XSHM
  if (xcontext->use_xshm) {
    int expected_size;

    meta->xvimage = XvShmCreateImage (xcontext->disp,
        xcontext->xv_port_id, im_format, NULL, width, height, &meta->SHMInfo);
    if (!meta->xvimage || error_caught) {
      g_mutex_unlock (&xvimagesink->x_lock);

      /* Reset error flag */
      error_caught = FALSE;

      /* Push a warning */
      GST_ELEMENT_WARNING (xvimagesink, RESOURCE, WRITE,
          ("Failed to create output image buffer of %dx%d pixels",
              width, height),
          ("could not XShmCreateImage a %dx%d image", width, height));

      /* Retry without XShm */
      xvimagesink->xcontext->use_xshm = FALSE;

      /* Hold X mutex again to try without XShm */
      g_mutex_lock (&xvimagesink->x_lock);
      goto no_xshm;
    }

    /* we have to use the returned data_size for our shm size */
    meta->size = meta->xvimage->data_size;
    GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
        meta->size);

    /* calculate the expected size.  This is only for sanity checking the
     * number we get from X. */
    switch (im_format) {
      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
      {
        gint pitches[3];
        gint offsets[3];
        guint plane;

        offsets[0] = 0;
        pitches[0] = GST_ROUND_UP_4 (width);
        offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (height);
        pitches[1] = GST_ROUND_UP_8 (width) / 2;
        offsets[2] = offsets[1] + pitches[1] * GST_ROUND_UP_2 (height) / 2;
        pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;

        expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (height) / 2;

        for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
          GST_DEBUG_OBJECT (xvimagesink,
              "Plane %u has a expected pitch of %d bytes, " "offset of %d",
              plane, pitches[plane], offsets[plane]);
        }
        break;
      }
      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
        expected_size = height * GST_ROUND_UP_4 (width * 2);
        break;
      default:
        expected_size = 0;
        break;
    }
    if (expected_size != 0 && meta->size != expected_size) {
      GST_WARNING_OBJECT (xvimagesink,
          "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
          meta->size, expected_size);
    }

    /* Be verbose about our XvImage stride */
    {
      guint plane;

      for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
        GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
            "offset of %d", plane, meta->xvimage->pitches[plane],
            meta->xvimage->offsets[plane]);
      }
    }

    /* get shared memory */
    meta->SHMInfo.shmid =
        shmget (IPC_PRIVATE, meta->size + align, IPC_CREAT | 0777);
    if (meta->SHMInfo.shmid == -1)
      goto shmget_failed;

    /* attach */
    meta->SHMInfo.shmaddr = shmat (meta->SHMInfo.shmid, NULL, 0);
    if (meta->SHMInfo.shmaddr == ((void *) -1))
      goto shmat_failed;

    /* now we can set up the image data */
    meta->xvimage->data = meta->SHMInfo.shmaddr;
    meta->SHMInfo.readOnly = FALSE;

    if (XShmAttach (xcontext->disp, &meta->SHMInfo) == 0)
      goto xattach_failed;

    XSync (xcontext->disp, FALSE);

    /* Delete the shared memory segment as soon as we everyone is attached.
     * This way, it will be deleted as soon as we detach later, and not
     * leaked if we crash. */
    shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);

    GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
        meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
  } else
  no_xshm:
#endif /* HAVE_XSHM */
  {
    meta->xvimage = XvCreateImage (xcontext->disp,
        xcontext->xv_port_id, im_format, NULL, width, height);
    if (!meta->xvimage || error_caught)
      goto create_failed;

    /* we have to use the returned data_size for our image size */
    meta->size = meta->xvimage->data_size;
    meta->xvimage->data = g_malloc (meta->size + align);

    XSync (xcontext->disp, FALSE);
  }

  if ((offset = ((guintptr) meta->xvimage->data & align)))
    offset = (align + 1) - offset;

  GST_DEBUG_OBJECT (xvimagesink, "memory %p, align %d, offset %d",
      meta->xvimage->data, align, offset);

  /* Reset error handler */
  error_caught = FALSE;
  XSetErrorHandler (handler);

  gst_buffer_append_memory (buffer,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, meta->xvimage->data,
          meta->size + align, offset, meta->size, NULL, NULL));

  g_mutex_unlock (&xvimagesink->x_lock);

  success = TRUE;

beach:
  if (!success)
    meta = NULL;

  return meta;

  /* ERRORS */
create_failed:
  {
    g_mutex_unlock (&xvimagesink->x_lock);
    /* Reset error handler */
    error_caught = FALSE;
    XSetErrorHandler (handler);
    /* Push an error */
    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
        ("Failed to create output image buffer of %dx%d pixels",
            width, height),
        ("could not XvShmCreateImage a %dx%d image", width, height));
    goto beach;
  }
#ifdef HAVE_XSHM
shmget_failed:
  {
    g_mutex_unlock (&xvimagesink->x_lock);
    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
        ("Failed to create output image buffer of %dx%d pixels",
            width, height),
        ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
            meta->size));
    goto beach;
  }
shmat_failed:
  {
    g_mutex_unlock (&xvimagesink->x_lock);
    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
        ("Failed to create output image buffer of %dx%d pixels",
            width, height), ("Failed to shmat: %s", g_strerror (errno)));
    /* Clean up the shared memory segment */
    shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
    goto beach;
  }
xattach_failed:
  {
    /* Clean up the shared memory segment */
    shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
    g_mutex_unlock (&xvimagesink->x_lock);

    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
        ("Failed to create output image buffer of %dx%d pixels",
            width, height), ("Failed to XShmAttach"));
    goto beach;
  }
#endif
}
Beispiel #11
0
int xv_init( xv_handle_t handle, Display *dpy, __u32 fourcc, int width, int height, int bpp )
{
	unsigned int version, release;
	unsigned int request_base, event_base, error_base;
	
	int i;

	if( XvQueryExtension( dpy, &version, &release, &request_base, &event_base, &error_base ) != Success )
	{
#ifdef DEBUG
		fprintf( stderr, "XvQueryExtension failed\n" );
#endif
		return -1;
	}
	
	if( XvQueryAdaptors( dpy, DefaultRootWindow( dpy ), &handle->num_adaptors, &handle->p_adaptor_info ) != Success )
	{
#ifdef DEBUG
		fprintf( stderr, "XvQueryAdaptors failed\n" );
#endif
		return -1;
	}

/* 	printf( "%d adaptors found\n", handle->num_adaptors ); */
	
	if( handle->num_adaptors == 0 )
	{
		return -2;
	}
	

	for( i = 0; i < handle->num_adaptors; i++ )
	{
/* 		int format; */
		unsigned int num_encodings;
		XvEncodingInfo *p_encoding_info;
		int encoding;

		XvAttribute *at;
		unsigned int num_attributes;
		int attribute;

		XvImageFormatValues *xvimage_formats;
		unsigned int num_xvimage_formats;
		int format;
		

#ifdef DEBUG
		printf( "Adaptor: %d\n", i );
		printf( "Name: %s\n", handle->p_adaptor_info[i].name );
		printf( "Ports: %lu\n", handle->p_adaptor_info[i].num_ports );
		printf( "Formats: %lu\n", handle->p_adaptor_info[i].num_formats );
		
		for( format = 0; format < handle->p_adaptor_info[i].num_formats; format++ )
		{
			printf( "+Format: %d\n", format );
			printf( " +Depth: %d\n", handle->p_adaptor_info[i].formats[format].depth );
			printf( " +VisualID: %lu\n", handle->p_adaptor_info[i].formats[format].visual_id );
		}

			
		if( XvQueryEncodings( dpy, handle->p_adaptor_info[i].base_id, &num_encodings, &p_encoding_info ) != Success )
		{
			fprintf( stderr, "XvQueryEncodings failed\n" );
		}
		printf( " +num_encodings: %d\n", num_encodings );
		
		for( encoding = 0; encoding < num_encodings; encoding++ )
		{
			printf( "  +Encoding: %d\n", encoding );
			printf( "  +Name: %s\n", p_encoding_info[encoding].name );
			printf( "  +Resolution: %lu x %lu\n", 
					p_encoding_info[encoding].width, 
					p_encoding_info[encoding].height );
		}
#endif //DEBUG

		at = XvQueryPortAttributes( dpy, handle->p_adaptor_info[i].base_id, &num_attributes );
#ifdef DEBUG
		printf( "num_attributes: %d\n", num_attributes );
#endif
		for( attribute = 0; attribute < num_attributes; attribute++ )
		{
			int val;
			Atom atom;
			
			if( !strcmp( at[attribute].name, "XV_COLORKEY" ) )
			{
#ifdef DEBUG
				printf( "attribute: %d\n", attribute );
				printf( "name: %s\n", at[attribute].name );
#endif
				atom = (Atom)XInternAtom( dpy, at[attribute].name, 0 );
#ifdef DEBUG
				printf( "atom: %p\n", atom );
#endif
				XvGetPortAttribute( dpy, 
									handle->p_adaptor_info[i].base_id, 
									atom, 
									&val );
#ifdef DEBUG
				printf( "Attribute: %d\n", attribute );
				printf( "Name: %s\n", at[attribute].name );
				printf( "min: %x\n", at[attribute].min_value );
				printf( "max: %x\n", at[attribute].max_value );
				printf( "value: %x\n", val );
#endif
				handle->atom_colorkey = XInternAtom( dpy, at[attribute].name, 0 );
			}
			if( !strcmp( at[attribute].name, "XV_BRIGHTNESS" ) )
			{
				handle->atom_brightness = XInternAtom( dpy, at[attribute].name, 0 );
				handle->brightness_min = at[attribute].min_value;
				handle->brightness_max = at[attribute].max_value;
			}
			if( !strcmp( at[attribute].name, "XV_HUE" ) )
			{
				handle->atom_hue = XInternAtom( dpy, at[attribute].name, 0 );
				handle->hue_min = at[attribute].min_value;
				handle->hue_max = at[attribute].max_value;
			}
			if( !strcmp( at[attribute].name, "XV_CONTRAST" ) )
			{
				handle->atom_contrast = XInternAtom( dpy, at[attribute].name, 0 );
				handle->contrast_min = at[attribute].min_value;
				handle->contrast_max = at[attribute].max_value;
			}
			if( !strcmp( at[attribute].name, "XV_DOUBLE_BUFFER" ) )
			{
				Atom _atom;
				_atom = XInternAtom( dpy, at[attribute].name, 0 );
				XvSetPortAttribute( dpy, handle->p_adaptor_info[i].base_id, _atom, 1 );
#ifdef DEBUG
				printf( "Xv: DOUBLE_BUFFER available\n" );
#endif
			}	
		}

		xvimage_formats = XvListImageFormats( dpy, handle->p_adaptor_info[i].base_id, &num_xvimage_formats );
/* 		printf( "num_xvimage_formats: %d\n", num_xvimage_formats ); */
		for( format = 0; format < num_xvimage_formats; format++ )
		{
			char imageName[5] = {0, 0, 0, 0, 0};
			memcpy(imageName, &(xvimage_formats[format].id), 4);
#ifdef DEBUG
			fprintf(stdout, "      id: 0x%x", xvimage_formats[format].id);
#endif
			if( isprint( imageName[0]) && isprint(imageName[1]) &&
			    isprint( imageName[2]) && isprint(imageName[3])) 
			{
#ifdef DEBUG
				fprintf(stdout, " (%s)\n", imageName);
#endif
				if( xvimage_formats[format].id == fourcc )
				{
					handle->xv_mode_id = fourcc;
					break;
				}
			} else {
#ifdef DEBUG
				fprintf(stdout, "\n");
#endif
			}
		}

		if( handle->xv_mode_id != fourcc )
		{
			return -3;
		}

		if( XvGrabPort( dpy, handle->p_adaptor_info[i].base_id, CurrentTime ) != Success )
		{
/* 			fprintf( stderr, "Failed to grab port!\n" ); */
			return -1;
		}
	}

	handle->use_shm = 1;

	if( handle->use_shm )
	{
		memset( &handle->shminfo, 0, sizeof( XShmSegmentInfo ) );
		handle->image = XvShmCreateImage( dpy, 
						  handle->p_adaptor_info[0].base_id, 
						  handle->xv_mode_id, 
						  (char*)NULL, 
						  width,
						  height, 
						  &handle->shminfo );

		if( handle->image )
		{
			handle->shminfo.shmid = shmget( IPC_PRIVATE, handle->image->data_size, IPC_CREAT | 0777 );
			if( handle->shminfo.shmid == -1 )
			{
/* 				fprintf( stderr, "shmget failed\n" ); */
				return -1;
			}
			handle->shminfo.shmaddr = handle->image->data = shmat( handle->shminfo.shmid, 0, 0 );
			shmctl(handle->shminfo.shmid, IPC_RMID, 0);
			/* destroy when we terminate, now if shmat failed */

			if( handle->shminfo.shmaddr == ( void * ) -1 )
			{
/* 				fprintf( stderr, "shmat failed\n" ); */
				return -1;
			}
			
			handle->shminfo.readOnly = False;
			if( !XShmAttach( dpy, &handle->shminfo ) )
			{
/* 				fprintf( stderr, "XShmAttach failed\n" ); */
				shmdt( handle->shminfo.shmaddr );
				XFree( handle->image );
				return -1;
			}
		}
		else
		{
/* 			fprintf( stderr, "XvShmCreateImage failed\n" ); */
			return -1;
		}
	}
	else
	{
		char * data = (char*) malloc( width*height*(bpp/8));
		handle->image = XvCreateImage( dpy, handle->p_adaptor_info[0].base_id, handle->xv_mode_id, data, width, height );
	}	

	handle->display = dpy;

	return 0;
}
Beispiel #12
0
int svlWindowManagerX11::DoModal(bool show, bool fullscreen)
{
    Destroy();
    DestroyFlag = false;

    unsigned int i, atom_count;
    int x, y, prevright, prevbottom;
    unsigned int lastimage = 0;
    unsigned long black, white;
    XSizeHints wsh;

#if CISST_SVL_HAS_XV
    Atom atoms[3];
    unsigned int xvadaptorcount;
    XvAdaptorInfo *xvai;
    XVisualInfo xvvinfo;
    bool xvupdateimage = true;
#else // CISST_SVL_HAS_XV
    Atom atoms[2];
#endif // CISST_SVL_HAS_XV

    // setting decoration hints for borderless mode
    struct {
        unsigned long 	flags;
        unsigned long 	functions;
        unsigned long 	decorations;
        signed long 	input_mode;
        unsigned long 	status;
    } mwm;
    mwm.flags = MWM_HINTS_DECORATIONS;
    mwm.decorations = 0;
    mwm.functions = 0;
    mwm.input_mode = 0;
    mwm.status = 0;
    
    // resetting DestroyedSignal event
    if (DestroyedSignal) delete(DestroyedSignal);
    DestroyedSignal = new osaThreadSignal();
    if (DestroyedSignal == 0) goto labError;

    // initialize display and pick default screen
    xDisplay = XOpenDisplay(reinterpret_cast<char*>(0));
    xScreen = DefaultScreen(xDisplay);

#if CISST_SVL_HAS_XV
    // check if 24bpp is suppoted by the display
    if (XMatchVisualInfo(xDisplay, xScreen, 24, TrueColor, &xvvinfo) == 0) goto labError;
#endif // CISST_SVL_HAS_XV

    // pick colors
    black = BlackPixel(xDisplay, xScreen);
    white = WhitePixel(xDisplay, xScreen);

    // create windows
    xWindows = new Window[NumOfWins];
    memset(xWindows, 0, NumOfWins * sizeof(Window));
    xGCs = new GC[NumOfWins];
    memset(xGCs, 0, NumOfWins * sizeof(GC));

    // create atoms for overriding default window behaviours
    atoms[0] = XInternAtom(xDisplay, "WM_DELETE_WINDOW", False);
    atoms[1] = XInternAtom(xDisplay, "_MOTIF_WM_HINTS", False);
#if CISST_SVL_HAS_XV
    atoms[2] = XInternAtom(xDisplay, "XV_SYNC_TO_VBLANK", False);
#endif // CISST_SVL_HAS_XV

    // create title strings
    Titles = new std::string[NumOfWins];
    CustomTitles = new std::string[NumOfWins];
    CustomTitleEnabled = new int[NumOfWins];

#if CISST_SVL_HAS_XV
    xvImg = new XvImage*[NumOfWins];
    xvShmInfo = new XShmSegmentInfo[NumOfWins];
    xvPort = new XvPortID[NumOfWins];
    if (xvImg == 0 || xvShmInfo == 0 || xvPort == 0) goto labError;
    memset(xvImg, 0, NumOfWins * sizeof(XvImage*));
    memset(xvShmInfo, 0, NumOfWins * sizeof(XShmSegmentInfo));
    memset(xvPort, 0, NumOfWins * sizeof(XvPortID));
#else // CISST_SVL_HAS_XV
    // create images
    xImageBuffers = new unsigned char*[NumOfWins];
    for (i = 0; i < NumOfWins; i ++) {
        xImageBuffers[i] = new unsigned char[Width[i] * Height[i] * 4];
    }
    xImg = new XImage*[NumOfWins];
    memset(xImg, 0, NumOfWins * sizeof(XImage*));
    if (xImg == 0) goto labError;
    for (i = 0; i < NumOfWins; i ++) {
        xImg[i] = XCreateImage(xDisplay,
                               DefaultVisual(xDisplay, xScreen),
                               24,
                               ZPixmap,
                               0,
                               reinterpret_cast<char*>(xImageBuffers[i]),
                               Width[i],
                               Height[i],
                               32,
                               0);
    }
#endif // CISST_SVL_HAS_XV

    prevright = prevbottom = 0;
    for (i = 0; i < NumOfWins; i ++) {
        if (PosX == 0 || PosY == 0) {
            if (fullscreen) {
                x = prevright;
                y = 0;
                prevright += Width[i];
            }
            else {
                x = prevright;
                y = prevbottom;
                prevright += 50;
                prevbottom += 50;
            }
        }
        else {
            x = PosX[i];
            y = PosY[i];
        }

        xWindows[i] = XCreateSimpleWindow(xDisplay, DefaultRootWindow(xDisplay),
                                          x,
                                          y,
                                          Width[i],
                                          Height[i],
                                          0,
                                          black,
                                          white);
        if (xWindows[i] == 0) goto labError;

        // overriding default behaviours:
        //    - borderless mode
        //    - closing window
        if (fullscreen) {
            XChangeProperty(xDisplay, xWindows[i],
                            atoms[1], atoms[1], 32,
                            PropModeReplace, reinterpret_cast<unsigned char*>(&mwm), 5);
            atom_count = 2;
        }
        else {
            atom_count = 1;
        }
        XSetWMProtocols(xDisplay, xWindows[i], atoms, atom_count);

        wsh.flags = PPosition|PSize;
        wsh.x = x;
        wsh.y = y;
        wsh.width = Width[i];
        wsh.height = Height[i];
        XSetNormalHints(xDisplay, xWindows[i], &wsh);

        // set window title
        CustomTitleEnabled[i] = 0;

        std::ostringstream ostring;
        if (Title.length() > 0) {
            if (NumOfWins > 0) ostring << Title << " #" << i;
            else ostring << Title;
        }
        else {
            if (NumOfWins > 0) ostring << Title << "svlImageWindow #" << i;
            else ostring << "svlImageWindow";
        }

        Titles[i] = ostring.str();
        XSetStandardProperties(xDisplay, xWindows[i],
                               Titles[i].c_str(), Titles[i].c_str(),
                               None, NULL, 0, NULL);

        // set even mask
        XSelectInput(xDisplay, xWindows[i], ExposureMask|PointerMotionMask|ButtonPressMask|KeyPressMask);

        // set window colormap
        XSetWindowColormap(xDisplay, xWindows[i], DefaultColormapOfScreen(DefaultScreenOfDisplay(xDisplay)));

#if CISST_SVL_HAS_XV
        // query shared memory extension
        if (!XShmQueryExtension(xDisplay)) goto labError;

        // query video adaptors
        if (XvQueryAdaptors(xDisplay, DefaultRootWindow(xDisplay), &xvadaptorcount, &xvai) != Success) goto labError;
        xvPort[i] = xvai->base_id + i;
        XvFreeAdaptorInfo(xvai);

        // overriding default Xvideo vertical sync behavior
        XvSetPortAttribute (xDisplay, xvPort[i], atoms[2], 1);
#endif // CISST_SVL_HAS_XV

        // create graphics context
        xGCs[i] = XCreateGC(xDisplay, xWindows[i], 0, 0);

        // set default colors
        XSetBackground(xDisplay, xGCs[i], white);
        XSetForeground(xDisplay, xGCs[i], black);

#if CISST_SVL_HAS_XV
        // create image in shared memory
        xvImg[i] = XvShmCreateImage(xDisplay, xvPort[i], 0x32595559/*YUV2*/, 0, Width[i], Height[i], &(xvShmInfo[i]));
        if (xvImg[i]->width < static_cast<int>(Width[i]) || xvImg[i]->height < static_cast<int>(Height[i])) {
            CMN_LOG_INIT_ERROR << "DoModal - image too large for XV to display (requested="
                               << Width[i] << "x" << Height[i] << "; allowed="
                               << xvImg[i]->width << "x" << xvImg[i]->height << ")" << std::endl;
            goto labError;
        }
        xvShmInfo[i].shmid = shmget(IPC_PRIVATE, xvImg[i]->data_size, IPC_CREAT | 0777);
        xvShmInfo[i].shmaddr = xvImg[i]->data = reinterpret_cast<char*>(shmat(xvShmInfo[i].shmid, 0, 0));
        xvShmInfo[i].readOnly = False;
        if (!XShmAttach(xDisplay, &(xvShmInfo[i]))) goto labError;
#endif // CISST_SVL_HAS_XV

        // clear window
        XClearWindow(xDisplay, xWindows[i]);

        // show window if requested
        if (show) XMapRaised(xDisplay, xWindows[i]);
    }

    // signal that initialization is done
    if (InitReadySignal) InitReadySignal->Raise();

	// main message loop
    XEvent event;
    KeySym code;
    unsigned int winid;

    while (1) {
        osaSleep(0.001);
#if CISST_SVL_HAS_XV
        if (!xvupdateimage) {
            for (int events = XPending(xDisplay); events > 0; events --) {
#else // CISST_SVL_HAS_XV
        if (XPending(xDisplay)) {
#endif // CISST_SVL_HAS_XV
                XNextEvent(xDisplay, &event);

                // find recipient
                for (winid = 0; winid < NumOfWins; winid ++) {
                    if (event.xany.window == xWindows[winid]) break;
                }
                if (winid == NumOfWins) continue;

                // override default window behaviour
                if (event.type == ClientMessage) {
                    if (static_cast<unsigned long>(event.xclient.data.l[0]) == atoms[0]) {
                        // X11 server wants to close window
                        // Do nothing.... we will destroy it ourselves later
                    }
                    continue;
                }

                // window should be closed
                if (event.type == UnmapNotify) {
                    printf("destroy\n");
                    if (xGCs[winid]) {
                        XFreeGC(xDisplay, xGCs[winid]);
                        xGCs[winid] = 0;
                    }
                    xWindows[winid] = 0;
                    continue;
                }

                // window should be updated
                if (event.type == Expose && event.xexpose.count == 0) {
                    XClearWindow(xDisplay, xWindows[winid]);
                    continue;
                }

                if (event.type == KeyPress) {
                    code = XLookupKeysym(&event.xkey, 0);
                    if (code >= 48 && code <= 57) { // ascii numbers
                        OnUserEvent(winid, true, code);
                        continue;
                    }
                    if (code >= 97 && code <= 122) { // ascii letters
                        OnUserEvent(winid, true, code);
                        continue;
                    }
                    if (code == 13 ||
                        code == 32) { // special characters with correct ascii code
                        OnUserEvent(winid, true, code);
                        continue;
                    }
                    if (code >= 0xffbe && code <= 0xffc9) { // F1-F12
                        OnUserEvent(winid, false, winInput_KEY_F1 + (code - 0xffbe));
                        continue;
                    }
                    switch (code) {
                        case 0xFF55:
                            OnUserEvent(winid, false, winInput_KEY_PAGEUP);
                        break;

                        case 0xFF56:
                            OnUserEvent(winid, false, winInput_KEY_PAGEDOWN);
                        break;

                        case 0xFF50:
                            OnUserEvent(winid, false, winInput_KEY_HOME);
                        break;

                        case 0xFF57:
                            OnUserEvent(winid, false, winInput_KEY_END);
                        break;

                        case 0xFF63:
                            OnUserEvent(winid, false, winInput_KEY_INSERT);
                        break;

                        case 0xFFFF:
                            OnUserEvent(winid, false, winInput_KEY_DELETE);
                        break;

                        case 0xFF51:
                            OnUserEvent(winid, false, winInput_KEY_LEFT);
                        break;

                        case 0xFF53:
                            OnUserEvent(winid, false, winInput_KEY_RIGHT);
                        break;

                        case 0xFF52:
                            OnUserEvent(winid, false, winInput_KEY_UP);
                        break;

                        case 0xFF54:
                            OnUserEvent(winid, false, winInput_KEY_DOWN);
                        break;
                    }
                    continue;
                }

                if (event.type == ButtonPress) {
                    if (event.xbutton.button == Button1) {
                        if (!LButtonDown && !RButtonDown) {
                            LButtonDown = true;
                            XGrabPointer(xDisplay, xWindows[winid], false,
                                         PointerMotionMask|ButtonReleaseMask,
                                         GrabModeAsync, GrabModeAsync,
                                         None,
                                         None,
                                         CurrentTime);
                        }
                        OnUserEvent(winid, false, winInput_LBUTTONDOWN);
                    }
                    else if (event.xbutton.button == Button3) {
                        if (!LButtonDown && !RButtonDown) {
                            RButtonDown = true;
                            XGrabPointer(xDisplay, xWindows[winid], false,
                                         PointerMotionMask|ButtonReleaseMask,
                                         GrabModeAsync, GrabModeAsync,
                                         None,
                                         None,
                                         CurrentTime);
                        }
                        OnUserEvent(winid, false, winInput_RBUTTONDOWN);
                    }
                }
                
                if (event.type == ButtonRelease) {
                    if (event.xbutton.button == Button1) {
                        OnUserEvent(winid, false, winInput_LBUTTONUP);
                        if (LButtonDown && !RButtonDown) {
                            LButtonDown = false;
                            XUngrabPointer(xDisplay, CurrentTime);
                        }
                    }
                    else if (event.xbutton.button == Button3) {
                        OnUserEvent(winid, false, winInput_RBUTTONUP);
                        if (!LButtonDown && RButtonDown) {
                            RButtonDown = false;
                            XUngrabPointer(xDisplay, CurrentTime);
                        }
                    }
                }

                if (event.type == MotionNotify) {
                    SetMousePos(static_cast<short>(event.xmotion.x), static_cast<short>(event.xmotion.y));
                    OnUserEvent(winid, false, winInput_MOUSEMOVE);
                }

#if CISST_SVL_HAS_XV
                // image update complete
                if (event.type == XShmGetEventBase(xDisplay) + ShmCompletion) {
                    xvupdateimage = true;
                    continue;
                }
            }
            if (!xvupdateimage) signalImage.Wait(0.01);
#endif // CISST_SVL_HAS_XV
        }
        else {
            if (DestroyFlag) break;

            if (ImageCounter > lastimage) {
                csImage.Enter();
                    lastimage = ImageCounter;

#if CISST_SVL_HAS_XV
                    for (i = 0; i < NumOfWins; i ++) {
                        XvShmPutImage(xDisplay,
                                      xvPort[i],
                                      xWindows[i],
                                      xGCs[i],
                                      xvImg[i],
                                      0, 0, Width[i], Height[i],
                                      0, 0, Width[i], Height[i], True);
                    }
                    xvupdateimage = false;
#else // CISST_SVL_HAS_XV
                    for (i = 0; i < NumOfWins; i ++) {
                        xImg[i]->data = reinterpret_cast<char*>(xImageBuffers[i]);
                        XPutImage(xDisplay,
                                  xWindows[i],
                                  xGCs[i],
                                  xImg[i],
                                  0, 0, 0, 0,
                                  Width[i], Height[i]);
                    }
#endif // CISST_SVL_HAS_XV
/*
                    for (i = 0; i < NumOfWins; i ++) {
                        if (CustomTitleEnabled[i] < 0) {
                            // Restore original timestamp
                            XSetStandardProperties(xDisplay, xWindows[i],
                                                   Titles[i].c_str(), Titles[i].c_str(),
                                                   None, NULL, 0, NULL);
                        }
                        else if (CustomTitleEnabled[i] > 0) {
                            // Set custom timestamp
                            XSetStandardProperties(xDisplay, xWindows[i],
                                                   CustomTitles[i].c_str(), CustomTitles[i].c_str(),
                                                   None, NULL, 0, NULL);
                        }
                    }
*/
                csImage.Leave();
            }
        }
    }

labError:

#if CISST_SVL_HAS_XV
    if (xvShmInfo) {
        for (i = 0; i < NumOfWins; i ++) {
            XShmDetach(xDisplay, &(xvShmInfo[i]));
            shmdt(xvShmInfo[i].shmaddr);
        }
        delete [] xvShmInfo; 
        xvShmInfo = 0;
    }
#endif // CISST_SVL_HAS_XV
    XSync(xDisplay, 0);
    for (i = 0; i < NumOfWins; i ++) {
        if (xGCs[i]) XFreeGC(xDisplay, xGCs[i]);
        if (xWindows[i]) XDestroyWindow(xDisplay, xWindows[i]);
    }
    XCloseDisplay(xDisplay);
#if CISST_SVL_HAS_XV
    if (xvImg) {
        for (i = 0; i < NumOfWins; i ++) {
            if (xvImg[i]) XFree(xvImg[i]); 
        }
        delete [] xvImg; 
        xvImg = 0;
    }
    if (xvPort) {
        delete [] xvPort; 
        xvPort = 0;
    }
#else // CISST_SVL_HAS_XV
    if (xImg) {
        for (i = 0; i < NumOfWins; i ++) {
            if (xImg[i]) XDestroyImage(xImg[i]); 
        }
        delete [] xImg; 
        xImg = 0;
    }
    if (xImageBuffers) {
        delete [] xImageBuffers;
        xImageBuffers = 0;
    }
#endif // CISST_SVL_HAS_XV
    if (xGCs) {
        delete [] xGCs;
        xGCs = 0;
    }
    if (xWindows) {
        delete [] xWindows;
        xWindows = 0;
    }
    if (Titles) {
        delete [] Titles;
        Titles = 0;
    }
    if (CustomTitles) {
        delete [] CustomTitles;
        CustomTitles = 0;
    }
    if (CustomTitleEnabled) {
        delete [] CustomTitleEnabled;
        CustomTitleEnabled = 0;
    }

    xScreen = 0;
    xDisplay = 0;

    if (DestroyedSignal) DestroyedSignal->Raise();

    return 0;
}
Beispiel #13
0
void XVWindow::ShmAttach(int imageWidth, int imageHeight)
{
  unsigned int i = 0;
  for (i = 0; i < NUM_BUFFERS; i++) {

    if (_useShm) {
      // create the shared memory portion
      _XVImage[i] = XvShmCreateImage (_display, _XVPort, GUID_YV12_PLANAR, 0, imageWidth, imageHeight, &_XShmInfo[i]);
  
      if (_XVImage[i] == NULL) {
        PTRACE(1, "XVideo\tXShmCreateImage failed");
        _useShm = false;
      }
  
      if ((_XVImage[i]) && (_XVImage[i]->id != GUID_YV12_PLANAR)) {
        PTRACE(1, "XVideo\t  XvShmCreateImage returned a different colorspace than YV12");
        XFree (_XVImage[i]);
        _useShm = false;
      }
    }

#if PTRACING
    if (_useShm) {
      int j = 0;
      PTRACE(4, "XVideo\tCreated XvImage (" << _XVImage[i]->width << "x" << _XVImage[i]->height
             << ", data size: " << _XVImage[i]->data_size << ", num_planes: " << _XVImage[i]->num_planes);

      for (j = 0 ; j < _XVImage[i]->num_planes ; j++)
        PTRACE(4, "XVideo\t  Plane " << j << ": pitch=" << _XVImage[i]->pitches [j] << ", offset=" << _XVImage[i]->offsets [j]);
    }
#endif

    if (_useShm) {
      _XShmInfo[i].shmid = shmget (IPC_PRIVATE, _XVImage[i]->data_size, IPC_CREAT | 0777);
      if (_XShmInfo[i].shmid < 0) {
        XFree (_XVImage[i]);
        PTRACE(1, "XVideo\tshmget failed"); //strerror(errno)
        _useShm = FALSE;
      }
    }
  
    if (_useShm) {
      _XShmInfo[i].shmaddr = (char *) shmat(_XShmInfo[i].shmid, 0, 0);
      if (_XShmInfo[i].shmaddr == ((char *) -1)) {
        XFree (_XVImage[i]);
        _XVImage[i] = NULL;
        PTRACE(1, "XVideo\tshmat failed"); //strerror(errno)
        _useShm = FALSE;
      }
    }
  
    if (_useShm) {
      _XVImage[i]->data = _XShmInfo[i].shmaddr;
      _XShmInfo[i].readOnly = False;
  
      // Attaching the shared memory to the display
      XErrorHandler oldHandler = XSetErrorHandler((XErrorHandler) catchXShmError);
      Status status = XShmAttach (_display, &_XShmInfo[i]);
      XSync(_display, False);
      XSetErrorHandler((XErrorHandler) oldHandler);

      if ( (status != True) || (_shmError) ) {
        XFree (_XVImage[i]);
        _XVImage[i] = NULL;
        if (_XShmInfo[i].shmaddr != ((char *) -1)) {
          shmdt(_XShmInfo[i].shmaddr);
        }
        PTRACE(1, "XVideo\t  XShmAttach failed");
        if ( (status == True) && (_shmError) ) {
          PTRACE(1, "XVideo\t  X server supports SHM but apparently we are remotely connected...");
        }
        _useShm = false;
      } 
    } 
  
    if (_useShm) {
      shmctl(_XShmInfo[i].shmid, IPC_RMID, 0);
    }
  }
}
Beispiel #14
0
void XvMCOSD::CreateBuffer(XvMCContext &xvmc_ctx, int width, int height)
{
    if (NO_SUBPICTURE == osd_subpict_mode)
    {
        VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed because "
                "no subpicture is available");
        osd_subpict_alloc = false;
        return;
    }

    XJ_width = width;
    XJ_height = height;

    osd_subpict_clear_color = 0;
    int ret = Success;
    X11S(ret = XvMCCreateSubpicture(XJ_disp, &xvmc_ctx, &osd_subpict,
                                    XJ_width, XJ_height, osd_subpict_info.id));

    if (ret != Success)
    {
        VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed on XvMCCreateSubpicture");
        osd_subpict_mode = NO_SUBPICTURE;
        osd_subpict_alloc = false;
        return;
    }

    X11L;
    XvMCClearSubpicture(XJ_disp, &osd_subpict, 0, 0, XJ_width,
                        XJ_height, osd_subpict_clear_color);

    osd_xv_image = XvShmCreateImage(XJ_disp, xv_port,
                                    osd_subpict_info.id, NULL,
                                    XJ_width, XJ_height,
                                    &XJ_osd_shm_info);
    X11U;

    if (!osd_xv_image)
    {
        VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed on XvShmCreateImage");
        osd_subpict_mode = NO_SUBPICTURE;
        osd_subpict_alloc = false;
        return;
    }
    XJ_osd_shm_info.shmid = shmget(IPC_PRIVATE, osd_xv_image->data_size,
                                   IPC_CREAT | 0777);
    XJ_osd_shm_info.shmaddr = (char *)shmat(XJ_osd_shm_info.shmid, 0, 0);
    XJ_osd_shm_info.readOnly = False;

    osd_xv_image->data = XJ_osd_shm_info.shmaddr;

    X11S(XShmAttach(XJ_disp, &XJ_osd_shm_info));

    shmctl(XJ_osd_shm_info.shmid, IPC_RMID, 0);

    if (osd_subpict.num_palette_entries > 0)
    {
        int snum = osd_subpict.num_palette_entries;
        int seb = osd_subpict.entry_bytes;

        osd_palette = new unsigned char[snum * seb];

        for (int i = 0; i < snum; i++)
        {
            int Y = i * (1 << osd_subpict_info.y_sample_bits) / snum;
            int U = 1 << (osd_subpict_info.u_sample_bits - 1);
            int V = 1 << (osd_subpict_info.v_sample_bits - 1);
            for (int j = 0; j < seb; j++)
            {
                switch (osd_subpict.component_order[j]) 
                {
                    case 'U': osd_palette[i * seb + j] = U; break;
                    case 'V': osd_palette[i * seb + j] = V; break;
                    case 'Y':
                    default:  osd_palette[i * seb + j] = Y; break;
                }
            }
        }

        X11S(XvMCSetSubpicturePalette(XJ_disp, &osd_subpict, osd_palette));
    }
    osd_subpict_alloc = true;
}
Beispiel #15
0
int
xf_video_process_frame(xfInfo * xfi, RD_VIDEO_FRAME_EVENT * vevent)
{
	XShmSegmentInfo shminfo;
	XvImage * image;
	int colorkey = 0;
	int i;
	uint32 pixfmt;
	uint8 * data1;
	uint8 * data2;

	if (xfi->xv_port == -1)
		return 1;

	/* In case the player is minimized */
	if (vevent->x < -2048 || vevent->y < -2048 || vevent->num_visible_rects <= 0)
		return 0;

	if (xfi->xv_colorkey_atom != None)
	{
		XvGetPortAttribute(xfi->display, xfi->xv_port, xfi->xv_colorkey_atom, &colorkey);
		XSetFunction(xfi->display, xfi->gc, GXcopy);
		XSetFillStyle(xfi->display, xfi->gc, FillSolid);
		XSetForeground(xfi->display, xfi->gc, colorkey);
		for (i = 0; i < vevent->num_visible_rects; i++)
		{
			XFillRectangle(xfi->display, xfi->wnd, xfi->gc,
				vevent->x + vevent->visible_rects[i].x,
				vevent->y + vevent->visible_rects[i].y,
				vevent->visible_rects[i].width,
				vevent->visible_rects[i].height);
		}
	}

	pixfmt = vevent->frame_pixfmt;
	image = XvShmCreateImage(xfi->display, xfi->xv_port,
		pixfmt, 0, vevent->frame_width, vevent->frame_height, &shminfo);
	if (xfi->xv_image_size != image->data_size)
	{
		if (xfi->xv_image_size > 0)
		{
			shmdt(xfi->xv_shmaddr);
			shmctl(xfi->xv_shmid, IPC_RMID, NULL);
		}
		xfi->xv_image_size = image->data_size;
		xfi->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
		xfi->xv_shmaddr = shmat(xfi->xv_shmid, 0, 0);
	}
	shminfo.shmid = xfi->xv_shmid;
	shminfo.shmaddr = image->data = xfi->xv_shmaddr;
	shminfo.readOnly = False;
  
	if (!XShmAttach(xfi->display, &shminfo))
	{
		XFree(image);
		printf("xf_video_process_frame: XShmAttach failed.\n");
		return 1;
	}

	/* The video driver may align each line to a different size
	   and we need to convert our original image data. */
	switch (pixfmt)
	{
		case RD_PIXFMT_I420:
		case RD_PIXFMT_YV12:
			if (!xf_video_is_format_supported(xfi, RD_PIXFMT_I420) &&
				!xf_video_is_format_supported(xfi, RD_PIXFMT_YV12))
			{
				printf("xf_video_process_frame: pixel format 0x%X not supported by hardware.\n", pixfmt);
				break;
			}
			/* Y */
			if (image->pitches[0] == vevent->frame_width)
			{
				memcpy(image->data + image->offsets[0],
					vevent->frame_data,
					vevent->frame_width * vevent->frame_height);
			}
			else
			{
				for (i = 0; i < vevent->frame_height; i++)
				{
					memcpy(image->data + image->offsets[0] + i * image->pitches[0],
						vevent->frame_data + i * vevent->frame_width,
						vevent->frame_width);
				}
			}
			/* UV */
			/* Conversion between I420 and YV12 is to simply swap U and V */
			if (xf_video_is_format_supported(xfi, pixfmt))
			{
				data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height;
				data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height +
					vevent->frame_width * vevent->frame_height / 4;
			}
			else
			{
				data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height;
				data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height +
					vevent->frame_width * vevent->frame_height / 4;
				image->id = pixfmt == RD_PIXFMT_I420 ? RD_PIXFMT_YV12 : RD_PIXFMT_I420;
			}
			if (image->pitches[1] * 2 == vevent->frame_width)
			{
				memcpy(image->data + image->offsets[1],
					data1,
					vevent->frame_width * vevent->frame_height / 4);
				memcpy(image->data + image->offsets[2],
					data2,
					vevent->frame_width * vevent->frame_height / 4);
			}
			else
			{
				for (i = 0; i < vevent->frame_height / 2; i++)
				{
					memcpy(image->data + image->offsets[1] + i * image->pitches[1],
						data1 + i * vevent->frame_width / 2,
						vevent->frame_width / 2);
					memcpy(image->data + image->offsets[2] + i * image->pitches[2],
						data2 + i * vevent->frame_width / 2,
						vevent->frame_width / 2);
				}
			}
			break;

		default:
			memcpy(image->data, vevent->frame_data, image->data_size <= vevent->frame_size ?
				image->data_size : vevent->frame_size);
			break;
	}

	XvShmPutImage(xfi->display, xfi->xv_port, xfi->wnd, xfi->gc_default, image,
		0, 0, image->width, image->height,
		vevent->x, vevent->y, vevent->width, vevent->height, False);
	XSync(xfi->display, False);

	XShmDetach(xfi->display, &shminfo);
	XFree(image);

	return 0;
}
//------------------------------------
//
//------------------------------------
uint8_t GUI_XvInit(GUI_WindowInfo * window, uint32_t w, uint32_t h)
{


    unsigned int ver, rel, req, ev, err;
    unsigned int port, adaptors;
    static XvAdaptorInfo *ai;
    static XvAdaptorInfo *curai;
    
#if 0
    win = gtk_widget_get_parent_window(window);
    xv_display = GDK_WINDOW_XDISPLAY(win);
//      xv_win= RootWindow(xv_display,0);
    xv_win = GDK_WINDOW_XWINDOW(GTK_WIDGET(window)->window);
#endif    

    xv_display=(Display *)window->display;
    xv_win=window->window;
    
    
#define WDN xv_display
    xv_port = 0;

    if (Success != XvQueryExtension(WDN, &ver, &rel, &req, &ev, &err))
      {
	  printf("\n Query Extension failed\n");
	  goto failed;
      }
    /* check for Xvideo support */
    if (Success != XvQueryAdaptors(WDN,
				   DefaultRootWindow(WDN), &adaptors, &ai))
      {
	  printf("\n Query Adaptor failed\n");
	  goto failed;
      }
    curai = ai;
    XvFormat *formats;
    // Dump infos
    port = 0;
    for (uint16_t i = 0; (!port) && (i < adaptors); i++)
      {
/*
XvPortID base_id;
unsigned long num_ports;
char type;
char *name;
unsigned long num_formats;
XvFormat *formats;
unsigned long num_adaptors;
*/
#ifdef VERBOSE_XV
	  printf("\n_______________________________\n");
	  printf("\n Adaptor 		: %d", i);
	  printf("\n Base ID		: %ld", curai->base_id);
	  printf("\n Nb Port	 	: %lu", curai->num_ports);
	  printf("\n Type			 	: %d,",
		 curai->type);
#define CHECK(x) if(curai->type & x) printf("|"#x);
	  CHECK(XvInputMask);
	  CHECK(XvOutputMask);
	  CHECK(XvVideoMask);
	  CHECK(XvStillMask);
	  CHECK(XvImageMask);

	  printf("\n Name			 	: %s",
		 curai->name);
	  printf("\n Num Adap	 	: %lu", curai->num_adaptors);
	  printf("\n Num fmt	 	: %lu", curai->num_formats);
#endif	  
	  formats = curai->formats;

	  //
	  uint16_t k;

	  for (k = 0; (k < curai->num_ports) && !port; k++)
	    {
		if (GUI_XvList(WDN, k + curai->base_id, &xv_format))
		    port = k + curai->base_id;
	    }


	  curai++;
      }
    //
    if (!port)
      {
	  printf("\n no port found");
	  goto failed;
      }
#ifdef 	COLORSPACE_YV12
    printf("\n Xv YV12 found at port :%d, format : %ld", port, xv_format);
#else
    printf("\n Xv YUY2 found at port :%d, format : %ld", port, xv_format);
#endif

    if (Success != XvGrabPort(WDN, port, 0))
	goto failed;
    {
	
	xv_port = port;
/*
   Display *display,
   XvPortID port,
   int id,
   char* data,
   int width,
   int height,
   XShmSegmentInfo *shminfo

*/
        
        XSetWindowAttributes xswa;
        XWindowAttributes attribs;
        static Atom xv_atom;
        unsigned long xswamask;
        int erCode;

        /* check if colorkeying is needed */
        xv_atom = getAtom( "XV_AUTOPAINT_COLORKEY" );
        if(xv_atom!=None)
        {
                XvSetPortAttribute( xv_display, xv_port, xv_atom, 1 );
        }
        else printf("No autopaint \n");

        /* if we have to deal with colorkeying ... */
        
	xvimage = XvShmCreateImage(WDN, xv_port,
				   xv_format, 0, w, h, &Shminfo);

	Shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size,
			       IPC_CREAT | 0777);
        if(Shminfo.shmid<=0)
        {
                printf("shmget failed\n");
        }
	Shminfo.shmaddr = (char *) shmat(Shminfo.shmid, 0, 0);
	Shminfo.readOnly = False;
        if(Shminfo.shmaddr==(char *)-1)
        {
                printf("Shmat failed\n");
        }
	xvimage->data = Shminfo.shmaddr;
	XShmAttach(WDN, &Shminfo);
	XSync(WDN, False);
	erCode=shmctl(Shminfo.shmid, IPC_RMID, 0);
        if(erCode)
        {
                printf("Shmctl failed :%d\n",erCode);
        }
	memset(xvimage->data, 0, xvimage->data_size);

	xv_xgc.graphics_exposures = False;

	xv_gc = XCreateGC(xv_display, xv_win, 0L, &xv_xgc);
	
	//ADM_assert(BadWindow!=XSelectInput(xv_display, xv_win, ExposureMask | VisibilityChangeMask));

    }
    printf("\n Xv init succeedeed\n");

    return 1;
  failed:
    printf("\n Xv init failed..\n");
    return 0;
}
Beispiel #17
0
static int X11_xshm_xv_blit(struct DriverInstance* sh,
                            const uint8_t* fb,
                            int width, int height,
                            struct blit_params* params,
                            int needs_adjust,
                            char* error_text, int text_len)
{
  // wait until last blit has completed
  if (sh->event_pending)
    {
      int max_wait = 15;
      XEvent event;
      sh->event_pending = 0;
      
      while (max_wait--)
        {
          XNextEvent(sh->display, &event);

          if (event.type == sh->completion_type)
            break;          
        }
    }


  if (sh->xv_image == 0 ||
      width  != sh->image_width ||
      height != sh->image_height)
    {
      if (sh->xv_image)
        XFree(sh->xv_image);

      sh->xv_image = XvShmCreateImage(sh->display,
                                      sh->xv_port,
                                      sh->xv_format_id,
                                      sh->shminfo.shmaddr,
                                      width, height,
                                      &sh->shminfo);
      sh->image_width  = width;
      sh->image_height = height;
    }

  //TODO: this is a hack for big-endian machines
  if (big_endian())
    convert_endianness((uint8_t*) fb, sh->width, sh->height);

  if (sh->vis.depth == 24)
    {
#if defined(OPT_INCLUDE_MMX)
      if (sh->mmx_supported)
        cvt_rgb32_to_i420_mmx((uint8_t*) sh->xv_image->data,
                              (uint32_t*) fb, width, height,
                              sh->xv_image->pitches, sh->xv_image->offsets);
      else
#endif
        cvt_rgb32_to_i420((uint8_t*) sh->xv_image->data,
                          (uint32_t*) fb, width, height,
                          sh->xv_image->pitches, sh->xv_image->offsets);
    }
  else if (sh->vis.depth == 16)
    cvt_rgb16_to_i420((uint8_t*) sh->xv_image->data,
                      (uint16_t*) fb, width, height,
                      sh->xv_image->pitches, sh->xv_image->offsets);

  // blit shared mem image
  XvShmPutImage(sh->display, sh->xv_port, sh->win, sh->gc, sh->xv_image,
                0, 0, width, height, 0, 0, sh->width, sh->height, True);
  sh->event_pending = 1;

  XFlush(sh->display);
  //XSync(sh->display, False);
  return 1;
}
/** The initialization function
  * This function opens the frame buffer device and allocates memory for display
  * also it finds the frame buffer supported display formats
  */
OMX_ERRORTYPE omx_xvideo_sink_component_Init(OMX_COMPONENTTYPE *openmaxStandComp) {
  omx_xvideo_sink_component_PrivateType* omx_xvideo_sink_component_Private = openmaxStandComp->pComponentPrivate;
  omx_xvideo_sink_component_PortType* pPort = (omx_xvideo_sink_component_PortType *) omx_xvideo_sink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX];
  int yuv_width  = pPort->sPortParam.format.video.nFrameWidth;
  int yuv_height = pPort->sPortParam.format.video.nFrameHeight;
  unsigned int err,i;

  omx_xvideo_sink_component_Private->dpy = XOpenDisplay(NULL);
  omx_xvideo_sink_component_Private->screen = DefaultScreen(omx_xvideo_sink_component_Private->dpy);

  XGetWindowAttributes(omx_xvideo_sink_component_Private->dpy,
    DefaultRootWindow(omx_xvideo_sink_component_Private->dpy),
    &omx_xvideo_sink_component_Private->attribs);

  XMatchVisualInfo(omx_xvideo_sink_component_Private->dpy,
    omx_xvideo_sink_component_Private->screen,
    omx_xvideo_sink_component_Private->attribs.depth, TrueColor, &
    omx_xvideo_sink_component_Private->vinfo);

  omx_xvideo_sink_component_Private->wmDeleteWindow = XInternAtom(omx_xvideo_sink_component_Private->dpy, "WM_DELETE_WINDOW", False);

  omx_xvideo_sink_component_Private->hint.x = 1;
  omx_xvideo_sink_component_Private->hint.y = 1;
  omx_xvideo_sink_component_Private->hint.width = yuv_width;
  omx_xvideo_sink_component_Private->hint.height = yuv_height;
  omx_xvideo_sink_component_Private->hint.flags = PPosition | PSize;

  omx_xvideo_sink_component_Private->xswa.colormap = XCreateColormap(omx_xvideo_sink_component_Private->dpy,
                                                                     DefaultRootWindow(omx_xvideo_sink_component_Private->dpy),
                                                                     omx_xvideo_sink_component_Private->vinfo.visual, AllocNone);
  omx_xvideo_sink_component_Private->xswa.event_mask = StructureNotifyMask | ExposureMask;
  omx_xvideo_sink_component_Private->xswa.background_pixel = 0;
  omx_xvideo_sink_component_Private->xswa.border_pixel = 0;

  omx_xvideo_sink_component_Private->window =
                        XCreateWindow(omx_xvideo_sink_component_Private->dpy,
                                      DefaultRootWindow(omx_xvideo_sink_component_Private->dpy), 0, 0, yuv_width,
                                      yuv_height, 0, omx_xvideo_sink_component_Private->vinfo.depth, InputOutput,
                                      omx_xvideo_sink_component_Private->vinfo.visual,
                                      CWBackPixel | CWBorderPixel | CWColormap |
                                      CWEventMask, &omx_xvideo_sink_component_Private->xswa);

  XSelectInput(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window, StructureNotifyMask);
  XSetStandardProperties(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window, "xvcam", "xvcam", None, NULL, 0,
                        &omx_xvideo_sink_component_Private->hint);

  XSetWMProtocols(omx_xvideo_sink_component_Private->dpy,
                  omx_xvideo_sink_component_Private->window,
                  &omx_xvideo_sink_component_Private->wmDeleteWindow, 1);
  XMapWindow(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window);

  if (XShmQueryExtension(omx_xvideo_sink_component_Private->dpy))
    omx_xvideo_sink_component_Private->CompletionType = XShmGetEventBase(omx_xvideo_sink_component_Private->dpy) + ShmCompletion;
  else
    return OMX_ErrorUndefined;

  if (Success !=
     XvQueryExtension(omx_xvideo_sink_component_Private->dpy,
                      &omx_xvideo_sink_component_Private->ver,
                      &omx_xvideo_sink_component_Private->rel,
                      &omx_xvideo_sink_component_Private->req,
                      &omx_xvideo_sink_component_Private->ev, &err))
    fprintf(stderr, "Couldn't do Xv stuff\n");

  if (Success !=
     XvQueryAdaptors(omx_xvideo_sink_component_Private->dpy,
                     DefaultRootWindow(omx_xvideo_sink_component_Private->dpy),
                     &omx_xvideo_sink_component_Private->adapt,
                     &omx_xvideo_sink_component_Private->ai))
    fprintf(stderr, "Couldn't do Xv stuff\n");

  for (i = 0; i < (int) omx_xvideo_sink_component_Private->adapt; i++) {
    omx_xvideo_sink_component_Private->xv_port = omx_xvideo_sink_component_Private->ai[i].base_id;
  }

  if (omx_xvideo_sink_component_Private->adapt > 0)
    XvFreeAdaptorInfo(omx_xvideo_sink_component_Private->ai);

  omx_xvideo_sink_component_Private->gc = XCreateGC(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window, 0, 0);

  omx_xvideo_sink_component_Private->yuv_image = XvShmCreateImage(omx_xvideo_sink_component_Private->dpy,
                                                                  omx_xvideo_sink_component_Private->xv_port,
                                                                  GUID_I420_PLANAR, 0, yuv_width,
                                                                  yuv_height, &omx_xvideo_sink_component_Private->yuv_shminfo);

  omx_xvideo_sink_component_Private->yuv_shminfo.shmid    = shmget(IPC_PRIVATE, omx_xvideo_sink_component_Private->yuv_image->data_size, IPC_CREAT | 0777);
  omx_xvideo_sink_component_Private->yuv_shminfo.shmaddr  = (char *) shmat(omx_xvideo_sink_component_Private->yuv_shminfo.shmid, 0, 0);
  omx_xvideo_sink_component_Private->yuv_image->data      = omx_xvideo_sink_component_Private->yuv_shminfo.shmaddr;
  omx_xvideo_sink_component_Private->yuv_shminfo.readOnly = False;

  if (!XShmAttach(omx_xvideo_sink_component_Private->dpy, &omx_xvideo_sink_component_Private->yuv_shminfo)) {
    printf("XShmAttach go boom boom!\n");
    return OMX_ErrorUndefined;
  }

  omx_xvideo_sink_component_Private->old_time = 0;
  omx_xvideo_sink_component_Private->new_time = 0;

  omx_xvideo_sink_component_Private->bIsXVideoInit = OMX_TRUE;
  /*Signal XVideo Initialized*/
  tsem_up(omx_xvideo_sink_component_Private->xvideoSyncSem);

  return OMX_ErrorNone;
}
Beispiel #19
0
static void xf_process_tsmf_video_frame_event(xfInfo* xfi, RDP_VIDEO_FRAME_EVENT* vevent)
{
	int i;
	BYTE* data1;
	BYTE* data2;
	UINT32 pixfmt;
	UINT32 xvpixfmt;
	BOOL converti420yv12 = FALSE;
	XvImage * image;
	int colorkey = 0;
	XShmSegmentInfo shminfo;
	xfXvContext* xv = (xfXvContext*) xfi->xv_context;

	if (xv->xv_port == 0)
		return;

	/* In case the player is minimized */
	if (vevent->x < -2048 || vevent->y < -2048 || vevent->num_visible_rects <= 0)
		return;

	if (xv->xv_colorkey_atom != None)
	{
		XvGetPortAttribute(xfi->display, xv->xv_port, xv->xv_colorkey_atom, &colorkey);
		XSetFunction(xfi->display, xfi->gc, GXcopy);
		XSetFillStyle(xfi->display, xfi->gc, FillSolid);
		XSetForeground(xfi->display, xfi->gc, colorkey);
		for (i = 0; i < vevent->num_visible_rects; i++)
		{
			XFillRectangle(xfi->display, xfi->window->handle, xfi->gc,
				vevent->x + vevent->visible_rects[i].x,
				vevent->y + vevent->visible_rects[i].y,
				vevent->visible_rects[i].width,
				vevent->visible_rects[i].height);
		}
	}
	else
	{
		XSetClipRectangles(xfi->display, xfi->gc, vevent->x, vevent->y,
			(XRectangle*) vevent->visible_rects, vevent->num_visible_rects, YXBanded);
	}

	pixfmt = vevent->frame_pixfmt;

	if (xf_tsmf_is_format_supported(xv, pixfmt))
	{
		xvpixfmt = pixfmt;
	}
	else if (pixfmt == RDP_PIXFMT_I420 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_YV12))
	{
		xvpixfmt = RDP_PIXFMT_YV12;
		converti420yv12 = TRUE;
	}
	else if (pixfmt == RDP_PIXFMT_YV12 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_I420))
	{
		xvpixfmt = RDP_PIXFMT_I420;
		converti420yv12 = TRUE;
	}
	else
	{
		DEBUG_XV("pixel format 0x%X not supported by hardware.", pixfmt);
		return;
	}

	image = XvShmCreateImage(xfi->display, xv->xv_port,
		xvpixfmt, 0, vevent->frame_width, vevent->frame_height, &shminfo);

	if (xv->xv_image_size != image->data_size)
	{
		if (xv->xv_image_size > 0)
		{
			shmdt(xv->xv_shmaddr);
			shmctl(xv->xv_shmid, IPC_RMID, NULL);
		}
		xv->xv_image_size = image->data_size;
		xv->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
		xv->xv_shmaddr = shmat(xv->xv_shmid, 0, 0);
	}
	shminfo.shmid = xv->xv_shmid;
	shminfo.shmaddr = image->data = xv->xv_shmaddr;
	shminfo.readOnly = FALSE;

	if (!XShmAttach(xfi->display, &shminfo))
	{
		XFree(image);
		DEBUG_XV("XShmAttach failed.");
		return;
	}

	/* The video driver may align each line to a different size
	   and we need to convert our original image data. */
	switch (pixfmt)
	{
		case RDP_PIXFMT_I420:
		case RDP_PIXFMT_YV12:
			/* Y */
			if (image->pitches[0] == vevent->frame_width)
			{
				memcpy(image->data + image->offsets[0],
					vevent->frame_data,
					vevent->frame_width * vevent->frame_height);
			}
			else
			{
				for (i = 0; i < vevent->frame_height; i++)
				{
					memcpy(image->data + image->offsets[0] + i * image->pitches[0],
						vevent->frame_data + i * vevent->frame_width,
						vevent->frame_width);
				}
			}
			/* UV */
			/* Conversion between I420 and YV12 is to simply swap U and V */
			if (converti420yv12 == FALSE)
			{
				data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height;
				data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height +
					vevent->frame_width * vevent->frame_height / 4;
			}
			else
			{
				data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height;
				data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height +
					vevent->frame_width * vevent->frame_height / 4;
				image->id = pixfmt == RDP_PIXFMT_I420 ? RDP_PIXFMT_YV12 : RDP_PIXFMT_I420;
			}
			if (image->pitches[1] * 2 == vevent->frame_width)
			{
				memcpy(image->data + image->offsets[1],
					data1,
					vevent->frame_width * vevent->frame_height / 4);
				memcpy(image->data + image->offsets[2],
					data2,
					vevent->frame_width * vevent->frame_height / 4);
			}
			else
			{
				for (i = 0; i < vevent->frame_height / 2; i++)
				{
					memcpy(image->data + image->offsets[1] + i * image->pitches[1],
						data1 + i * vevent->frame_width / 2,
						vevent->frame_width / 2);
					memcpy(image->data + image->offsets[2] + i * image->pitches[2],
						data2 + i * vevent->frame_width / 2,
						vevent->frame_width / 2);
				}
			}
			break;

		default:
			memcpy(image->data, vevent->frame_data, image->data_size <= vevent->frame_size ?
				image->data_size : vevent->frame_size);
			break;
	}

	XvShmPutImage(xfi->display, xv->xv_port, xfi->window->handle, xfi->gc, image,
		0, 0, image->width, image->height,
		vevent->x, vevent->y, vevent->width, vevent->height, FALSE);
	if (xv->xv_colorkey_atom == None)
		XSetClipMask(xfi->display, xfi->gc, None);
	XSync(xfi->display, FALSE);

	XShmDetach(xfi->display, &shminfo);
	XFree(image);
}
Beispiel #20
0
int main (int argc, char* argv[]) {
  int		yuv_width = 1024;
  int		yuv_height = 768;
  
  int		xv_port = -1;
  int		adaptor, encodings, attributes, formats;
  int		i, j, ret, p, _d, _w, _h;
  long		secsb, secsa, frames;
  
  XvAdaptorInfo		*ai;
  XvEncodingInfo	*ei;
  XvAttribute		*at;
  XvImageFormatValues	*fo;

  XvImage		*yuv_image;

#define GUID_YUV12_PLANAR 0x32315659

  unsigned int		p_version, p_release,
  			p_request_base, p_event_base, p_error_base;
  int			p_num_adaptors;
   	
  Display		*dpy;
  Window		window, _dw;
  XSizeHints		hint;
  XSetWindowAttributes	xswa;
  XVisualInfo		vinfo;
  int			screen;
  unsigned long		mask;
  XEvent		event;
  GC			gc;

  /** for shm */
  int 			shmem_flag = 0;
  XShmSegmentInfo	yuv_shminfo;
  int			CompletionType;


  printf("starting up video testapp...\n\n");
  
  adaptor = -1;
	
  dpy = XOpenDisplay(NULL);
  if (dpy == NULL) {
    printf("Cannot open Display.\n");
    exit (-1);
  }
  
  screen = DefaultScreen(dpy);
  
  /** find best display */
  if (XMatchVisualInfo(dpy, screen, 24, TrueColor, &vinfo)) {
    printf(" found 24bit TrueColor\n");
  } else
    if (XMatchVisualInfo(dpy, screen, 16, TrueColor, &vinfo)) {
      printf(" found 16bit TrueColor\n");
    } else
      if (XMatchVisualInfo(dpy, screen, 15, TrueColor, &vinfo)) {
	printf(" found 15bit TrueColor\n");
      } else
  	if (XMatchVisualInfo(dpy, screen, 8, PseudoColor, &vinfo)) {
	  printf(" found 8bit PseudoColor\n");
  	} else
	  if (XMatchVisualInfo(dpy, screen, 8, GrayScale, &vinfo)) {
	    printf(" found 8bit GrayScale\n");
	  } else
	    if (XMatchVisualInfo(dpy, screen, 8, StaticGray, &vinfo)) {
	      printf(" found 8bit StaticGray\n");
	    } else
	      if (XMatchVisualInfo(dpy, screen, 1, StaticGray, &vinfo)) {
  		printf(" found 1bit StaticGray\n");
	      } else {
  		printf("requires 16 bit display\n");
  		exit (-1);
	      }
  
  CompletionType = -1;	
  
  hint.x = 1;
  hint.y = 1;
  hint.width = yuv_width;
  hint.height = yuv_height;
  hint.flags = PPosition | PSize;
  
  xswa.colormap =  XCreateColormap(dpy, DefaultRootWindow(dpy), vinfo.visual, AllocNone);
  xswa.event_mask = StructureNotifyMask | ExposureMask;
  xswa.background_pixel = 0;
  xswa.border_pixel = 0;
  
  mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  
  window = XCreateWindow(dpy, DefaultRootWindow(dpy),
			 0, 0,
			 yuv_width,
			 yuv_height,
			 0, vinfo.depth,
			 InputOutput,
			 vinfo.visual,
			 mask, &xswa);
  
  XStoreName(dpy, window, "XV");
  XSetIconName(dpy, window, "XV");
  
  XSelectInput(dpy, window, StructureNotifyMask);
  
  /** Map window */
  XMapWindow(dpy, window);
  
  /** Wait for map. */
  do {
    XNextEvent(dpy, &event);
  }
  while (event.type != MapNotify || event.xmap.event != window);
  
  if (XShmQueryExtension(dpy)) shmem_flag = 1;
  if (!shmem_flag) {
    printf("no shmem available.\n");
    exit (-1);
  }
  
  if (shmem_flag==1) CompletionType = XShmGetEventBase(dpy) + ShmCompletion;
  
  
  /**--------------------------------- XV ------------------------------------*/
  printf("beginning to parse the Xvideo extension...\n\n");
  
  /** query and print Xvideo properties */
  ret = XvQueryExtension(dpy, &p_version, &p_release, &p_request_base,
			 &p_event_base, &p_error_base);
  if (ret != Success) {
    if (ret == XvBadExtension)
      printf("XvBadExtension returned at XvQueryExtension.\n");
    else
      if (ret == XvBadAlloc)
	printf("XvBadAlloc returned at XvQueryExtension.\n");
      else
	printf("other error happened at XvQueryExtension.\n");
  }
  printf("========================================\n");
  printf("XvQueryExtension returned the following:\n");
  printf("p_version      : %u\n", p_version);
  printf("p_release      : %u\n", p_release);
  printf("p_request_base : %u\n", p_request_base);
  printf("p_event_base   : %u\n", p_event_base);
  printf("p_error_base   : %u\n", p_error_base);
  printf("========================================\n");
  
  ret = XvQueryAdaptors(dpy, DefaultRootWindow(dpy),
			&p_num_adaptors, &ai);
  
  if (ret != Success) {
    if (ret == XvBadExtension)
      printf("XvBadExtension returned at XvQueryExtension.\n");
    else
      if (ret == XvBadAlloc)
	printf("XvBadAlloc returned at XvQueryExtension.\n");
      else
	printf("other error happaned at XvQueryAdaptors.\n");
  }
  printf("=======================================\n");
  printf("XvQueryAdaptors returned the following:\n");
  printf("%d adaptors available.\n", p_num_adaptors);
  for (i = 0; i < p_num_adaptors; i++) {
    printf(" name:        %s\n"
	   " type:        %s%s%s%s%s\n"
	   " ports:       %ld\n"
	   " first port:  %ld\n",
	   ai[i].name,
	   (ai[i].type & XvInputMask)	? "input | "	: "",
	   (ai[i].type & XvOutputMask)	? "output | "	: "",
	   (ai[i].type & XvVideoMask)	? "video | "	: "",
	   (ai[i].type & XvStillMask)	? "still | "	: "",
	   (ai[i].type & XvImageMask)	? "image | "	: "",
	   ai[i].num_ports,
	   ai[i].base_id);
    xv_port = ai[i].base_id;
    
    printf("adaptor %d ; format list:\n", i);
    for (j = 0; j < ai[i].num_formats; j++) {
      printf(" depth=%d, visual=%ld\n",
	     ai[i].formats[j].depth,
	     ai[i].formats[j].visual_id);
    }
    for (p = ai[i].base_id; p < ai[i].base_id+ai[i].num_ports; p++) {
      
      printf(" encoding list for port %d\n", p);
      if (XvQueryEncodings(dpy, p, &encodings, &ei) != Success) {
	printf("XvQueryEncodings failed.\n");
	continue;
      }
      for (j = 0; j < encodings; j++) {
	printf("  id=%ld, name=%s, size=%ldx%ld, numerator=%d, denominator=%d\n",
	       ei[j].encoding_id, ei[j].name, ei[j].width, ei[j].height,
	       ei[j].rate.numerator, ei[j].rate.denominator);
      }
      XvFreeEncodingInfo(ei);
      
      printf(" attribute list for port %d\n", p);
      at = XvQueryPortAttributes(dpy, p, &attributes);
      for (j = 0; j < attributes; j++) {
	printf("  name:       %s\n"
	       "  flags:     %s%s\n"
	       "  min_color:  %i\n"
	       "  max_color:  %i\n",
	       at[j].name,
	       (at[j].flags & XvGettable) ? " get" : "",
	       (at[j].flags & XvSettable) ? " set" : "",						
	       at[j].min_value, at[j].max_value);
      }
      if (at)
	XFree(at);
      
      printf(" image format list for port %d\n", p);
      fo = XvListImageFormats(dpy, p, &formats);
      for (j = 0; j < formats; j++) {
	printf("  0x%x (%4.4s) %s\n",
	       fo[j].id,
	       (char *)&fo[j].id,
	       (fo[j].format == XvPacked) ? "packed" : "planar");
      }
      if (fo)
	XFree(fo);
    }
    printf("\n");
  }
  if (p_num_adaptors > 0)
    XvFreeAdaptorInfo(ai);
  if (xv_port == -1)
    exit (0);
  
  gc = XCreateGC(dpy, window, 0, 0);		
  
  yuv_image = XvShmCreateImage(dpy, xv_port, GUID_YUV12_PLANAR, 0, yuv_width, yuv_height, &yuv_shminfo);
  yuv_shminfo.shmid = shmget(IPC_PRIVATE, yuv_image->data_size, IPC_CREAT | 0777);
  yuv_shminfo.shmaddr = yuv_image->data = shmat(yuv_shminfo.shmid, 0, 0);
  yuv_shminfo.readOnly = False;
  
  if (!XShmAttach(dpy, &yuv_shminfo)) {
    printf("XShmAttach failed !\n");
    exit (-1);
  }
  
  for (i = 0; i < yuv_image->height; i++) {
    for (j = 0; j < yuv_image->width; j++) {
      yuv_image->data[yuv_image->width*i + j] = i*j;
    }
  }
  
  printf("%d\n", yuv_image->data_size);
  int joe = 0;
  while (1) {
    frames = secsa = secsb = 0;
    time(&secsa);
    while (frames < 200) {	
        XGetGeometry(dpy, window, &_dw, &_d, &_d, &_w, &_h, &_d, &_d);
        for (i = 0; i < yuv_image->height * 1.5; i++) {
            for (j = 0; j < yuv_image->width; j++) {
                yuv_image->data[yuv_image->width*i + j] = (i + j + joe / 5);
            }
        }
   
      XvShmPutImage(dpy, xv_port, window, gc, yuv_image,
		    0, 0, yuv_image->width, yuv_image->height,
		    0, 0, _w, _h, True);
      
      /* XFlush(dpy); */
      joe++;
      frames++;
    }
    time(&secsb);
    printf("%ld frames in %ld seconds; %.4f fps\n", frames, secsb-secsa, (double) frames/(secsb-secsa));
  }
  
  return 0;
}
Beispiel #21
0
/* This function checks that it is actually really possible to create an image
   using XShm */
gboolean
gst_xvimagesink_check_xshm_calls (GstXvImageSink * xvimagesink,
    GstXContext * xcontext)
{
  XvImage *xvimage;
  XShmSegmentInfo SHMInfo;
  size_t size;
  int (*handler) (Display *, XErrorEvent *);
  gboolean result = FALSE;
  gboolean did_attach = FALSE;

  g_return_val_if_fail (xcontext != NULL, FALSE);

  /* Sync to ensure any older errors are already processed */
  XSync (xcontext->disp, FALSE);

  /* Set defaults so we don't free these later unnecessarily */
  SHMInfo.shmaddr = ((void *) -1);
  SHMInfo.shmid = -1;

  /* Setting an error handler to catch failure */
  error_caught = FALSE;
  handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);

  /* Trying to create a 1x1 picture */
  GST_DEBUG ("XvShmCreateImage of 1x1");
  xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
      xcontext->im_format, NULL, 1, 1, &SHMInfo);

  /* Might cause an error, sync to ensure it is noticed */
  XSync (xcontext->disp, FALSE);
  if (!xvimage || error_caught) {
    GST_WARNING ("could not XvShmCreateImage a 1x1 image");
    goto beach;
  }
  size = xvimage->data_size;

  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
  if (SHMInfo.shmid == -1) {
    GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
        size);
    goto beach;
  }

  SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
  if (SHMInfo.shmaddr == ((void *) -1)) {
    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
    /* Clean up the shared memory segment */
    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
    goto beach;
  }

  xvimage->data = SHMInfo.shmaddr;
  SHMInfo.readOnly = FALSE;

  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
    GST_WARNING ("Failed to XShmAttach");
    /* Clean up the shared memory segment */
    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
    goto beach;
  }

  /* Sync to ensure we see any errors we caused */
  XSync (xcontext->disp, FALSE);

  /* Delete the shared memory segment as soon as everyone is attached.
   * This way, it will be deleted as soon as we detach later, and not
   * leaked if we crash. */
  shmctl (SHMInfo.shmid, IPC_RMID, NULL);

  if (!error_caught) {
    GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
        SHMInfo.shmseg);

    did_attach = TRUE;
    /* store whether we succeeded in result */
    result = TRUE;
  } else {
    GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
        "Not using shared memory.");
  }

beach:
  /* Sync to ensure we swallow any errors we caused and reset error_caught */
  XSync (xcontext->disp, FALSE);

  error_caught = FALSE;
  XSetErrorHandler (handler);

  if (did_attach) {
    GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
        SHMInfo.shmid, SHMInfo.shmseg);
    XShmDetach (xcontext->disp, &SHMInfo);
    XSync (xcontext->disp, FALSE);
  }
  if (SHMInfo.shmaddr != ((void *) -1))
    shmdt (SHMInfo.shmaddr);
  if (xvimage)
    XFree (xvimage);
  return result;
}
int BC_Bitmap::allocate_data()
{
    int want_row_pointers = 1;

// Shared memory available
    if(use_shm)
    {
        switch(color_model)
        {
// Planar YUV.  Must use BC_WindowBase::accel_available before calling this.
        case BC_YUV420P:
        case BC_YUV422P:
// Packed YUV
        case BC_YUV422:
            ring_buffers = BITMAP_RING;
            xv_portid = top_level->xvideo_port_id;
// Create the X Image
            xv_image[0] = XvShmCreateImage(top_level->display,
                                           xv_portid,
                                           cmodel_bc_to_x(color_model),
                                           0,
                                           w,
                                           h,
                                           &shm_info);
// Create the shared memory
            shm_info.shmid = shmget(IPC_PRIVATE,
                                    xv_image[0]->data_size * ring_buffers + 4,
                                    IPC_CREAT | 0600);
            if(shm_info.shmid == -1) perror("BC_Bitmap::allocate_data shmget");
            data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
// setting ximage->data stops BadValue
            xv_image[0]->data = shm_info.shmaddr = (char*)data[0];
            shm_info.readOnly = 0;

// Get the real parameters
            w = xv_image[0]->width;
            h = xv_image[0]->height;

// Create remaining X Images
            for(int i = 1; i < ring_buffers; i++)
            {
                data[i] = data[0] + xv_image[0]->data_size * i;
                xv_image[i] = XvShmCreateImage(top_level->display,
                                               xv_portid,
                                               cmodel_bc_to_x(color_model),
                                               (char*)data[i],
                                               w,
                                               h,
                                               &shm_info);
                xv_image[i]->data = (char*)data[i];
            }

            if(color_model == BC_YUV422)
            {
                bytes_per_line = w * 2;
                bits_per_pixel = 2;
                want_row_pointers = 1;
            }
            else
            {
                bytes_per_line = 0;
                bits_per_pixel = 0;
                want_row_pointers = 0;
            }
            break;

        default:
// RGB
            ring_buffers = BITMAP_RING;
// Create first X Image
            ximage[0] = XShmCreateImage(top_level->display,
                                        top_level->vis,
                                        get_default_depth(),
                                        get_default_depth() == 1 ? XYBitmap : ZPixmap,
                                        (char*)NULL,
                                        &shm_info,
                                        w,
                                        h);

// Create shared memory
            shm_info.shmid = shmget(IPC_PRIVATE,
                                    h * ximage[0]->bytes_per_line * ring_buffers + 4,
                                    IPC_CREAT | 0600);
            if(shm_info.shmid == -1)
                perror("BC_Bitmap::allocate_data shmget");
            data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
            ximage[0]->data = shm_info.shmaddr = (char*)data[0];  // setting ximage->data stops BadValue
            shm_info.readOnly = 0;

// Get the real parameters
            bits_per_pixel = ximage[0]->bits_per_pixel;
            bytes_per_line = ximage[0]->bytes_per_line;

// Create remaining X Images
            for(int i = 1; i < ring_buffers; i++)
            {
                data[i] = data[0] + h * ximage[0]->bytes_per_line * i;
                ximage[i] = XShmCreateImage(top_level->display,
                                            top_level->vis,
                                            get_default_depth(),
                                            get_default_depth() == 1 ? XYBitmap : ZPixmap,
                                            (char*)data[i],
                                            &shm_info,
                                            w,
                                            h);
                ximage[i]->data = (char*)data[i];
//printf("BC_Bitmap::allocate_data %p\n", ximage[i]);
            }
            break;
        }

        if(!XShmAttach(top_level->display, &shm_info))
        {
            perror("BC_Bitmap::allocate_data XShmAttach");
        }

// This causes it to automatically delete when the program exits.
        shmctl(shm_info.shmid, IPC_RMID, 0);
    }
    else
// Use unshared memory.
    {
        ring_buffers = 1;
// need to use bytes_per_line for some X servers
        data[0] = 0;

// Use RGB frame
//printf("BCBitmap::allocate_data 1\n");
        ximage[0] = XCreateImage(top_level->display,
                                 top_level->vis,
                                 get_default_depth(),
                                 get_default_depth() == 1 ? XYBitmap : ZPixmap,
                                 0,
                                 (char*)data[0],
                                 w,
                                 h,
                                 8,
                                 0);
//printf("BCBitmap::allocate_data 1 %d\n", h * ximage[0]->bytes_per_line + 4);

        data[0] = (unsigned char*)malloc(h * ximage[0]->bytes_per_line + 4);
//printf("BCBitmap::allocate_data 2\n");

        XDestroyImage(ximage[0]);
//printf("BCBitmap::allocate_data 1\n");

        ximage[0] = XCreateImage(top_level->display,
                                 top_level->vis,
                                 get_default_depth(),
                                 get_default_depth() == 1 ? XYBitmap : ZPixmap,
                                 0,
                                 (char*)data[0],
                                 w,
                                 h,
                                 8,
                                 0);
//printf("BCBitmap::allocate_data 1\n");
// This differs from the depth parameter of the top_level.
        bits_per_pixel = ximage[0]->bits_per_pixel;
        bytes_per_line = ximage[0]->bytes_per_line;
//printf("BCBitmap::allocate_data 2\n");
    }

// Create row pointers
    if(want_row_pointers)
    {
//printf("BC_Bitmap::allocate 1 %d %d %d %d\n", w, h, get_default_depth(), bytes_per_line);
        for(int j = 0; j < ring_buffers; j++)
        {
            row_data[j] = new unsigned char*[h];
            for(int i = 0; i < h; i++)
            {
                row_data[j][i] = &data[j][i * bytes_per_line];
            }
        }
    }
    return 0;
}
SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
{
	SDL_Overlay *overlay;
	struct private_yuvhwdata *hwdata;
	int xv_port;
	int i, j;
	int adaptors;
	XvAdaptorInfo *ainfo;
	XShmSegmentInfo *yuvshm;

	xv_port = -1;
	if ( (Success == XvQueryExtension(GFX_Display, &j, &j, &j, &j, &j)) &&
	     (Success == XvQueryAdaptors(GFX_Display,
	                                 RootWindow(GFX_Display, SDL_Screen),
	                                 &adaptors, &ainfo)) ) {
		for ( i=0; (i<adaptors) && (xv_port == -1); ++i ) {
			if ( (ainfo[i].type & XvInputMask) &&
			     (ainfo[i].type & XvImageMask) ) {
				int num_formats;
				XvImageFormatValues *formats;
				formats = XvListImageFormats(GFX_Display,
				              ainfo[i].base_id, &num_formats);
				for ( j=0; j<num_formats; ++j ) {
					if ( (Uint32)formats[j].id == format ) {
						xv_port = ainfo[i].base_id;
						break;
					}
				}
			}
		}
	}
	if ( xv_port == -1 ) {
		SDL_SetError("No available video ports for requested format");
		return(NULL);
	}

	/* Create the overlay structure */
	overlay = (SDL_Overlay *)malloc(sizeof *overlay);
	if ( overlay == NULL ) {
		SDL_OutOfMemory();
		return(NULL);
	}
	memset(overlay, 0, (sizeof *overlay));

	/* Fill in the basic members */
	overlay->format = format;
	overlay->w = width;
	overlay->h = height;

	/* Set up the YUV surface function structure */
	overlay->hwfuncs = &x11_yuvfuncs;

	/* Create the pixel data and lookup tables */
	hwdata = (struct private_yuvhwdata *)malloc(sizeof *hwdata);
	overlay->hwdata = hwdata;
	if ( hwdata == NULL ) {
		SDL_OutOfMemory();
		SDL_FreeYUVOverlay(overlay);
		return(NULL);
	}
	yuvshm = &hwdata->yuvshm;
	memset(yuvshm, 0, sizeof(*yuvshm));
	hwdata->port = xv_port;
	hwdata->image = XvShmCreateImage(GFX_Display, xv_port, format,
	                                 0, width, height, yuvshm);
	if ( hwdata->image == NULL ) {
		SDL_OutOfMemory();
		SDL_FreeYUVOverlay(overlay);
		return(NULL);
	}
	yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size,
	                       IPC_CREAT | 0777);
	if ( yuvshm->shmid < 0 ) {
		SDL_SetError("Unable to get %d bytes shared memory",
		             hwdata->image->data_size);
		SDL_FreeYUVOverlay(overlay);
		return(NULL);
	}
	yuvshm->shmaddr  = (caddr_t) shmat(yuvshm->shmid, 0, 0);
	yuvshm->readOnly = False;
	hwdata->image->data = yuvshm->shmaddr;

	XShmAttach(GFX_Display, yuvshm);
	XSync(GFX_Display, False);
	shmctl(yuvshm->shmid, IPC_RMID, 0);

	/* We're all done.. */
	return(overlay);
}