Exemplo n.º 1
0
Arquivo: vo_xv.c Projeto: agiz/mpv
static inline void put_xvimage(struct vo *vo, XvImage *xvi)
{
    struct xvctx *ctx = vo->priv;
    struct vo_x11_state *x11 = vo->x11;
    struct mp_rect *src = &ctx->src_rect;
    struct mp_rect *dst = &ctx->dst_rect;
    int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0;
    int sw = src->x1 - src->x0, sh = src->y1 - src->y0;
#if HAVE_SHM
    if (ctx->Shmem_Flag) {
        XvShmPutImage(x11->display, ctx->xv_port, x11->window, x11->vo_gc, xvi,
                      src->x0, src->y0, sw, sh,
                      dst->x0, dst->y0, dw, dh,
                      True);
        x11->ShmCompletionWaitCount++;
    } else
#endif
    {
        XvPutImage(x11->display, ctx->xv_port, x11->window, x11->vo_gc, xvi,
                   src->x0, src->y0, sw, sh,
                   dst->x0, dst->y0, dw, dh);
    }
}
Exemplo n.º 2
0
void display_yuv_image(Display* display, XvPortID port, Drawable d, GC gc, XvImage* image, XShmSegmentInfo* shminfo,
                       int src_x, int src_y, unsigned int src_w, unsigned int src_h, struct xywh_s *dest,
                       double aspect_ratio)
{
    int dest_x = 0, dest_y = 0;
    int dest_w = dest->w;
    int dest_h = dest->h;

    /* Maybe keep aspect ratio of src image. */
    if (aspect_ratio == 0.0) {
        /*
         * Don't bother correcting any aspect ratio, just scale
         * to size as given.
         */
    } else if (dest_w * src_h < src_w * aspect_ratio * dest_h) {
        dest_y = dest_h;
        dest_h = dest_w * src_h / (src_w * aspect_ratio);
        dest_y = (dest_y - dest_h) / 2;
    } else {
        dest_x = dest_w;
        dest_w = dest_h * src_w * aspect_ratio / src_h;
        dest_x = (dest_x - dest_w) / 2;
    }

    /* Record (for the lightpen code) where the scaled screen ended up */
    dest->x = dest_x;
    dest->y = dest_y;
    dest->w = dest_w;
    dest->h = dest_h;

    if (shminfo) {
        XvShmPutImage(display, port, d, gc, image, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h, False);
    } else {
        XvPutImage(display, port, d, gc, image, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h);
    }
}
Exemplo n.º 3
0
int BC_Bitmap::write_drawable(Drawable &pixmap,
                              GC &gc,
                              int source_x,
                              int source_y,
                              int source_w,
                              int source_h,
                              int dest_x,
                              int dest_y,
                              int dest_w,
                              int dest_h,
                              int dont_wait)
{
//printf("BC_Bitmap::write_drawable 1 %p %d\n", this, current_ringbuffer);fflush(stdout);
    if(use_shm)
    {
        if(dont_wait) XSync(top_level->display, False);

        if(hardware_scaling())
        {
// printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
// 				source_y,
// 				source_w,
// 				source_h,
// 				dest_x,
// 				dest_y,
// 				dest_w,
// 				dest_h);
//for(int i = 0; i < 1000; i++) xv_image[current_ringbuffer]->data[i] = 255;
//printf("BC_Bitmap::write_drawable 2 %d %d %p %p\n", xv_portid,
//	pixmap,
//	gc,
//	xv_image[current_ringbuffer]);
            XvShmPutImage(top_level->display,
                          xv_portid,
                          pixmap,
                          gc,
                          xv_image[current_ringbuffer],
                          source_x,
                          source_y,
                          source_w,
                          source_h,
                          dest_x,
                          dest_y,
                          dest_w,
                          dest_h,
                          False);
// Need to pass these to the XvStopVideo
            last_pixmap = pixmap;
            last_pixmap_used = 1;
        }
        else
        {
// printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
// 				source_y,
// 				source_w,
// 				source_h,
// 				dest_x,
// 				dest_y,
// 				dest_w,
// 				dest_h);
            XShmPutImage(top_level->display,
                         pixmap,
                         gc,
                         ximage[current_ringbuffer],
                         source_x,
                         source_y,
                         dest_x,
                         dest_y,
                         dest_w,
                         dest_h,
                         False);
        }

// Force the X server into processing all requests.
// This allows the shared memory to be written to again.
        if(!dont_wait) XSync(top_level->display, False);
//TRACE("BC_Bitmap::write_drawable 5");
    }
    else
    {
        XPutImage(top_level->display,
                  pixmap,
                  gc,
                  ximage[current_ringbuffer],
                  source_x,
                  source_y,
                  dest_x,
                  dest_y,
                  dest_w,
                  dest_h);
    }

//printf("BC_Bitmap %d\n", current_ringbuffer);
    current_ringbuffer++;
    if(current_ringbuffer >= ring_buffers) current_ringbuffer = 0;
//printf("BC_Bitmap::write_drawable 2\n");fflush(stdout);
    return 0;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
void XVWindow::putFrame(uint8_t* frame, uint16_t width, uint16_t height) {
	XEvent event;

	if ((width!= _XVImage->width) || (height!=_XVImage->height)) {
	    printf ("[x11] dynamic switching of resolution not supported\n");
	    return;
	}

	// event handling
	while (XPending(_display)) {
		XNextEvent(_display, &event);
		if (event.type == ClientMessage) {
//			if "closeWindow" is clicked do nothing right now (window is closed from the Qt Gui
//			if (event.xclient.format == 32 && event.xclient.data.l[0] == (signed) WM_DELETE_WINDOW) exit(0);
		}
		// the window size has changed
		if (event.type == ConfigureNotify) {
			XConfigureEvent* xce = (XConfigureEvent*) &event;
			// if a slave window exists it has to be resized as well
			if (_slave) { _slave->resize(
				xce->width - (int)(xce->width / DEFAULT_SLAVE_RATIO),
				xce->height - (int)(_slave->getYUVHeight() * xce->width / DEFAULT_SLAVE_RATIO / _slave->getYUVWidth()),
				(int)(xce->width / DEFAULT_SLAVE_RATIO),
				(int)(_slave->getYUVHeight() * xce->width / DEFAULT_SLAVE_RATIO / _slave->getYUVWidth()));
			}

			// if we are a slave window the master window takes care of aspect ration
			if (_master) {
				_state.curX=0;
				_state.curY=0;
				_state.curWidth=xce->width;
				_state.curHeight=xce->height;
			// if we are a master window we have to recalculate the window size (important for non 4:3 screens)
			} else {
				if ((xce->width*_XVImage->height/_XVImage->width)>xce->height) {
					_state.curX=(int)((xce->width-(xce->height*_XVImage->width/_XVImage->height))/2);
					_state.curY=0;
					_state.curWidth=(int)(xce->height*_XVImage->width/_XVImage->height);
					_state.curHeight=xce->height;
				} else if ((xce->height*_XVImage->width/_XVImage->height)>xce->width) {
					_state.curX=0;
					_state.curY=(int)((xce->height-(xce->width*_XVImage->height/_XVImage->width))/2);
					_state.curWidth=xce->width;
					_state.curHeight=(int)(xce->width*_XVImage->height/_XVImage->width);
				} else {
					_state.curX=0;
					_state.curY=0;
					_state.curWidth=xce->width;
					_state.curHeight=xce->height;
				}
			}
		}

		// a key is pressed
		if (event.type == KeyPress) {
			XKeyEvent* xke = (XKeyEvent*) &event;
			switch (xke->keycode) {
				case 41:	toggleFullscreen(); // "f"
				break;
				case 40:	setDecoration(!_state.decoration); // "d"
				break;
				case 32:	toggleOntop(); // "o"
				break;
				case 9:		if (_state.fullscreen) { toggleFullscreen(); } // esc
				break;
			}
		}

		// a mouse button is clicked
		if (event.type == ButtonPress) {
			if (_master) {
				_master->toggleFullscreen();
			} else {
				toggleFullscreen();
			}
		}
	}

	// copy image to shared memory
	memcpy(_XVImage->data, frame, (int) (_XVImage->width * _XVImage->height * 3 /2));

	XvShmPutImage(_display, _XVPort, _XVWindow, _gc, _XVImage, 0, 0, _XVImage->width, _XVImage->height,
		_state.curX, _state.curY, _state.curWidth, _state.curHeight, True);

	XFlush(_display);
}
Exemplo n.º 7
0
static void x11video_process(MSFilter *f){
	X11Video *obj=(X11Video*)f->data;
	mblk_t *inm;
	int update=0;
	MSPicture lsrc={0};
	MSPicture src={0};
	MSRect mainrect,localrect;
	bool_t precious=FALSE;
	bool_t local_precious=FALSE;
	XWindowAttributes wa;
	MSTickerLateEvent late_info;

	ms_filter_lock(f);

	if ((obj->window_id == 0) || (x11_error == TRUE)) goto end;

	XGetWindowAttributes(obj->display,obj->window_id,&wa);
	if (x11_error == TRUE) {
		ms_error("Could not get window attributes for window %lu", obj->window_id);
		goto end;
	}
	if (wa.width!=obj->wsize.width || wa.height!=obj->wsize.height){
		ms_warning("Resized to %ix%i", wa.width,wa.height);
		obj->wsize.width=wa.width;
		obj->wsize.height=wa.height;
		XClearWindow(obj->display,obj->window_id);
	}

	ms_ticker_get_last_late_tick(f->ticker, &late_info);
	if(late_info.current_late_ms > 100) {
		ms_warning("Dropping frames because we're late");
		goto end;
	}

	if (!obj->show) {
		goto end;
	}
	if (!obj->ready){
		goto end;
	}

	if (f->inputs[0]!=NULL && (inm=ms_queue_peek_last(f->inputs[0]))!=0) {
		if (ms_yuv_buf_init_from_mblk(&src,inm)==0){
			MSVideoSize newsize;
			newsize.width=src.w;
			newsize.height=src.h;
			precious=mblk_get_precious_flag(inm);
			if (!ms_video_size_equal(newsize,obj->vsize) ) {
				ms_message("received size is %ix%i",newsize.width,newsize.height);
				obj->vsize=newsize;
				if (obj->autofit){
					MSVideoSize new_window_size;
					static const MSVideoSize min_size=MS_VIDEO_SIZE_QVGA;
					/*don't resize less than QVGA, it is too small*/
					if (min_size.width*min_size.height>newsize.width*newsize.height){
						new_window_size.width=newsize.width*2;
						new_window_size.height=newsize.height*2;
					}else new_window_size=newsize;
					obj->wsize=new_window_size;
					ms_message("autofit: new window size should be %ix%i",new_window_size.width,new_window_size.height);
					XResizeWindow(obj->display,obj->window_id,new_window_size.width,new_window_size.height);
					XSync(obj->display,FALSE);
				}
				x11video_unprepare(f);
				x11video_prepare(f);
				if (!obj->ready) goto end;
			}
		}
		update=1;
	}
	/*process last video message for local preview*/
	if (obj->corner!=-1 && f->inputs[1]!=NULL && (inm=ms_queue_peek_last(f->inputs[1]))!=0) {
		if (ms_yuv_buf_init_from_mblk(&lsrc,inm)==0){
			obj->lsize.width=lsrc.w;
			obj->lsize.height=lsrc.h;
			local_precious=mblk_get_precious_flag(inm);
			update=1;
		}
	}

	ms_layout_compute(obj->vsize, obj->vsize,obj->lsize,obj->corner,obj->scale_factor,&mainrect,&localrect);

	if (lsrc.w!=0 && obj->corner!=-1){
		/* first reduce the local preview image into a temporary image*/
		if (obj->local_msg==NULL){
			obj->local_msg=ms_yuv_buf_alloc(&obj->local_pic,localrect.w,localrect.h);
		}
		if (obj->sws2==NULL){
			obj->sws2=ms_scaler_create_context(lsrc.w,lsrc.h,MS_YUV420P,localrect.w,localrect.h,MS_YUV420P,
			                             MS_SCALER_METHOD_BILINEAR);
		}
		ms_scaler_process(obj->sws2,lsrc.planes,lsrc.strides,obj->local_pic.planes,obj->local_pic.strides);
		if (!local_precious) ms_yuv_buf_mirror(&obj->local_pic);
	}

	if (update && src.w!=0){
		ms_yuv_buf_copy(src.planes,src.strides,obj->fbuf.planes,obj->fbuf.strides,obj->vsize);
		if (obj->mirror && !precious) ms_yuv_buf_mirror(&obj->fbuf);
	}

	/*copy resized local view into a corner:*/
	if (update && obj->local_msg!=NULL && obj->corner!=-1){
		MSPicture corner=obj->fbuf;
		MSVideoSize roi;
		roi.width=obj->local_pic.w;
		roi.height=obj->local_pic.h;
		corner.w=obj->local_pic.w;
		corner.h=obj->local_pic.h;
		corner.planes[0]+=localrect.x+(localrect.y*corner.strides[0]);
		corner.planes[1]+=(localrect.x/2)+((localrect.y/2)*corner.strides[1]);
		corner.planes[2]+=(localrect.x/2)+((localrect.y/2)*corner.strides[2]);
		corner.planes[3]=0;
		ms_yuv_buf_copy(obj->local_pic.planes,obj->local_pic.strides,
				corner.planes,corner.strides,roi);
	}
	if (update){
		MSRect rect;
		ms_layout_center_rectangle(obj->wsize,obj->vsize,&rect);
		//ms_message("XvShmPutImage() %ix%i --> %ix%i",obj->fbuf.w,obj->fbuf.h,obj->wsize.width,obj->wsize.height);

		XvShmPutImage(obj->display,obj->port,obj->window_id,obj->gc, obj->xv_image,
		              0,0,obj->fbuf.w,obj->fbuf.h,
		              rect.x,rect.y,rect.w,rect.h,TRUE);
		XSync(obj->display,FALSE);
	}

end:
	ms_filter_unlock(f);
	if (f->inputs[0]!=NULL)
		ms_queue_flush(f->inputs[0]);
	if (f->inputs[1]!=NULL)
		ms_queue_flush(f->inputs[1]);
}
Exemplo n.º 8
0
bool QX11VideoSurface::present(const QVideoFrame &frame)
{
    if (!m_image) {
        setError(StoppedError);
        return false;
    } else if (m_image->width != frame.width() || m_image->height != frame.height()) {
        setError(IncorrectFormatError);
        return false;
    } else {
        QVideoFrame frameCopy(frame);

        if (!frameCopy.map(QAbstractVideoBuffer::ReadOnly)) {
            setError(IncorrectFormatError);
            return false;
        } else {
            bool presented = false;

            if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
                m_image->data_size > frame.mappedBytes()) {
                qWarning("Insufficient frame buffer size");
                setError(IncorrectFormatError);
            } else if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
                       m_image->num_planes > 0 &&
                       m_image->pitches[0] != frame.bytesPerLine()) {
                qWarning("Incompatible frame pitches");
                setError(IncorrectFormatError);
            } else {
                if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle) {
                    m_image->data = reinterpret_cast<char *>(frameCopy.bits());

                    //qDebug() << "copy frame";
                    XvPutImage(
                            QX11Info::display(),
                            m_portId,
                            m_winId,
                            m_gc,
                            m_image,
                            m_viewport.x(),
                            m_viewport.y(),
                            m_viewport.width(),
                            m_viewport.height(),
                            m_displayRect.x(),
                            m_displayRect.y(),
                            m_displayRect.width(),
                            m_displayRect.height());

                    m_image->data = 0;
                } else {
                    XvImage *img = frame.handle().value<XvImage*>();

                    //qDebug() << "render directly";
                    if (img)
                        XvShmPutImage(
                           QX11Info::display(),
                           m_portId,
                           m_winId,
                           m_gc,
                           img,
                           m_viewport.x(),
                           m_viewport.y(),
                           m_viewport.width(),
                           m_viewport.height(),
                           m_displayRect.x(),
                           m_displayRect.y(),
                           m_displayRect.width(),
                           m_displayRect.height(),
                           false);
                }

                presented = true;
            }

            frameCopy.unmap();

            return presented;
        }
    }
}
Exemplo n.º 9
0
void
S9xXVDisplayDriver::update (int width, int height)
{
    int   current_width, current_height, final_pitch;
    uint8 *final_buffer;
    int   dst_x, dst_y, dst_width, dst_height;
    GtkAllocation allocation;

    gtk_widget_get_allocation (drawing_area, &allocation);
    current_width = allocation.width;
    current_height = allocation.height;

    if (width <= 0)
    {
        gdk_window_hide (gdk_window);
        return;
    }

    if (output_window_width  != current_width ||
        output_window_height != current_height)
    {
        resize_window (current_width, current_height);
    }

    if (config->scale_method > 0)
    {
        uint8 *src_buffer = (uint8 *) padded_buffer[0];
        uint8 *dst_buffer = (uint8 *) padded_buffer[1];
        int   src_pitch = image_width * image_bpp;
        int   dst_pitch = scaled_max_width * image_bpp;

        S9xFilter (src_buffer,
                   src_pitch,
                   dst_buffer,
                   dst_pitch,
                   width,
                   height);

        final_buffer = (uint8 *) padded_buffer[1];
        final_pitch = dst_pitch;
    }
    else
    {
        final_buffer = (uint8 *) padded_buffer[0];
        final_pitch = image_width * image_bpp;
    }

    update_image_size (width, height);

    if (format == FOURCC_YUY2)
    {
        S9xConvertYUV (final_buffer,
                       (uint8 *) xv_image->data,
                       final_pitch,
                       2 * xv_image->width,
                       width + (width < xv_image->width ? (width % 2) + 4 : 0),
                       height + (height < xv_image->height ? 4 : 0));
    }
    else
    {
        S9xConvertMask (final_buffer,
                        (uint8 *) xv_image->data,
                        final_pitch,
                        bytes_per_pixel * xv_image->width,
                        width + (width < xv_image->width ? (width % 2) + 4 : 0),
                        height + (height < xv_image->height ? 4 : 0),
                        rshift,
                        gshift,
                        bshift,
                        bpp);
    }

    dst_x = width; dst_y = height;
    dst_width = current_width; dst_height = current_height;
    S9xApplyAspect (dst_x, dst_y, dst_width, dst_height);

    if (last_known_width != dst_width || last_known_height != dst_height)
    {
        last_known_width = dst_width;
        last_known_height = dst_height;
        clear ();
    }

    XvShmPutImage (display,
                   xv_portid,
                   xwindow,
                   XDefaultGC (display, XDefaultScreen (display)),
                   xv_image,
                   0,
                   0,
                   width,
                   height,
                   dst_x,
                   dst_y,
                   dst_width,
                   dst_height,
                   False);

    top_level->set_mouseable_area (dst_x, dst_y, dst_width, dst_height);

    XSync (display, False);

    return;
}
Exemplo n.º 10
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);
}
Exemplo n.º 11
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;
}
Exemplo n.º 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;
}
Exemplo n.º 13
0
void 
XVWindow::PutFrame (uint8_t* frame, 
                    uint16_t width, 
                    uint16_t height)
{
  if (!_XVImage[_curBuffer]) 
    return;
  
  if (width != _XVImage[_curBuffer]->width || height != _XVImage[_curBuffer]->height) {
     PTRACE (1, "XVideo\tDynamic switching of resolution not supported\n");
     return;
  }

  XLockDisplay (_display);

  if (_XVImage[_curBuffer]->pitches [0] ==_XVImage[_curBuffer]->width
      && _XVImage[_curBuffer]->pitches [2] == (int) (_XVImage[_curBuffer]->width / 2) 
      && _XVImage[_curBuffer]->pitches [1] == (int) (_XVImage[_curBuffer]->width / 2)) {
  
    memcpy (_XVImage[_curBuffer]->data, 
            frame, 
            (int) (_XVImage[_curBuffer]->width * _XVImage[_curBuffer]->height));
    memcpy (_XVImage[_curBuffer]->data + (int) (_XVImage[_curBuffer]->width * _XVImage[_curBuffer]->height), 
            frame + _XVImage[_curBuffer]->offsets [2], 
            (int) (_XVImage[_curBuffer]->width * _XVImage[_curBuffer]->height / 4));
    memcpy (_XVImage[_curBuffer]->data + (int) (_XVImage[_curBuffer]->width * _XVImage[_curBuffer]->height * 5 / 4), 
            frame + _XVImage[_curBuffer]->offsets [1], 
            (int) (_XVImage[_curBuffer]->width * _XVImage[_curBuffer]->height / 4));
  } 
  else {
  
    unsigned int i = 0;
    int width2 = (int) (_XVImage[_curBuffer]->width / 2);

    uint8_t* dstY = (uint8_t*) _XVImage[_curBuffer]->data;
    uint8_t* dstV = (uint8_t*) _XVImage[_curBuffer]->data + (_XVImage[_curBuffer]->pitches [0] * _XVImage[_curBuffer]->height);
    uint8_t* dstU = (uint8_t*) _XVImage[_curBuffer]->data + (_XVImage[_curBuffer]->pitches [0] * _XVImage[_curBuffer]->height) 
                                              + (_XVImage[_curBuffer]->pitches [1] * (_XVImage[_curBuffer]->height/2));

    uint8_t* srcY = frame;
    uint8_t* srcV = frame + (int) (_XVImage[_curBuffer]->width * _XVImage[_curBuffer]->height * 5 / 4);
    uint8_t* srcU = frame + (int) (_XVImage[_curBuffer]->width * _XVImage[_curBuffer]->height);

    for (i = 0 ; i < (unsigned int)_XVImage[_curBuffer]->height ; i+=2) {

      memcpy (dstY, srcY, _XVImage[_curBuffer]->width); 
      dstY +=_XVImage[_curBuffer]->pitches [0]; 
      srcY +=_XVImage[_curBuffer]->width;
      
      memcpy (dstY, srcY, _XVImage[_curBuffer]->width); 
      dstY +=_XVImage[_curBuffer]->pitches [0]; 
      srcY +=_XVImage[_curBuffer]->width;
      
      memcpy (dstV, srcV, width2); 
      dstV +=_XVImage[_curBuffer]->pitches [1]; 
      srcV += width2;
      
      memcpy(dstU, srcU, width2); dstU+=_XVImage[_curBuffer]->pitches [2]; 
      srcU += width2;
    }
  }
#ifdef HAVE_SHM
  if (_useShm) 
  {
    XvShmPutImage (_display, _XVPort, _XWindow, _gc, _XVImage[_curBuffer], 
                  0, 0, _XVImage[_curBuffer]->width, _XVImage[_curBuffer]->height, 
                  _state.curX, _state.curY, _state.curWidth, _state.curHeight, false);
  }
  else
#endif
  {
    XvPutImage (_display, _XVPort, _XWindow, _gc, _XVImage[_curBuffer], 
                  0, 0, _XVImage[_curBuffer]->width, _XVImage[_curBuffer]->height, 
                  _state.curX, _state.curY, _state.curWidth, _state.curHeight);
  }

  _curBuffer = (_curBuffer + 1) % NUM_BUFFERS;

  XUnlockDisplay (_display);

}
Exemplo n.º 14
0
static int display_frame(X11XVDisplaySink* sink, X11DisplayFrame* frame, const FrameInfo* frameInfo)
{
    struct timeval timeNow;
    long requiredUsec;
    long durationSlept;
    unsigned int windowWidth;
    unsigned int windowHeight;
    float scaleFactorX;
    float scaleFactorY;
    float scaleFactor;
    YUV_frame inputFrame;
    YUV_frame outputFrame;
    unsigned char* activeBuffer;
    int frameDurationMsec;
    int frameSlippage;

    frameDurationMsec = (int)(1000 * frameInfo->frameRate.den / (double)(frameInfo->frameRate.num));
    frameSlippage = frameDurationMsec * 1000 / 2; /* half a frame */


    if (frame->videoIsPresent)
    {
        /* convert if required */
        if (sink->inputVideoFormat == UYVY_10BIT_FORMAT)
        {
            if (sink->swScale != 1)
            {
                /* scale required afterwards */
                activeBuffer = frame->scaleInputBuffer;
            }
            else
            {
                /* no scale afterwards */
                activeBuffer = (unsigned char*)frame->yuv_image->data;
            }

            ConvertFrameV210to8(activeBuffer, frame->inputBuffer, sink->inputWidth * 2, (sink->inputWidth + 47) / 48 * 128,
                sink->inputWidth, sink->inputHeight);
        }
        else if (sink->inputVideoFormat == YUV444_FORMAT)
        {
            if (sink->swScale != 1)
            {
                /* scale required afterwards */
                activeBuffer = frame->scaleInputBuffer;
            }
            else
            {
                /* no scale afterwards */
                activeBuffer = (unsigned char*)frame->yuv_image->data;
            }

            yuv444_to_uyvy(sink->inputWidth, sink->inputHeight, frame->inputBuffer, activeBuffer);
        }
        else if (sink->inputVideoFormat == YUV422_FORMAT)
        {
            if (sink->swScale != 1)
            {
                /* scale required afterwards */
                activeBuffer = frame->scaleInputBuffer;
            }
            else
            {
                /* no scale afterwards */
                activeBuffer = (unsigned char*)frame->yuv_image->data;
            }

            yuv422_to_uyvy_2(sink->inputWidth, sink->inputHeight, 0, frame->inputBuffer, activeBuffer);
        }
        else if (sink->inputVideoFormat == YUV422_10BIT_FORMAT)
        {
            if (sink->swScale != 1)
            {
                /* scale required afterwards */
                activeBuffer = frame->scaleInputBuffer;
            }
            else
            {
                /* no scale afterwards */
                activeBuffer = (unsigned char*)frame->yuv_image->data;
            }

            ConvertFrameYUV10to8_2(frame->ditherOutputBuffer, (const uint16_t*)frame->inputBuffer, sink->inputWidth,
                                   sink->inputHeight, 2, 1);
            yuv422_to_uyvy_2(sink->inputWidth, sink->inputHeight, 0, frame->ditherOutputBuffer, activeBuffer);
        }
        else if (sink->inputVideoFormat == YUV420_10BIT_FORMAT)
        {
            if (sink->swScale != 1)
            {
                /* scale required afterwards */
                activeBuffer = frame->scaleInputBuffer;
            }
            else
            {
                /* no scale afterwards */
                activeBuffer = (unsigned char*)frame->yuv_image->data;
            }

            ConvertFrameYUV10to8_2(activeBuffer, (const uint16_t*)frame->inputBuffer, sink->inputWidth,
                                   sink->inputHeight, 2, 2);
        }
        else
        {
            /* no conversion - scale input frame->input buffer != frame->yuv_image->data */
            activeBuffer = frame->inputBuffer;
        }

        /* scale image and output to frame->yuv_image */
        if (sink->swScale != 1)
        {
            YUV_frame_from_buffer(&inputFrame, (void*)activeBuffer,
                sink->inputWidth, sink->inputHeight, sink->outputYUVFormat);

            YUV_frame_from_buffer(&outputFrame, (void*)(unsigned char*)frame->yuv_image->data,
                sink->width, sink->height, sink->outputYUVFormat);

            small_pic(&inputFrame,
                &outputFrame,
                0,
                0,
                sink->swScale,
                sink->swScale,
                1,
                sink->applyScaleFilter,
                sink->applyScaleFilter,
                frame->scaleWorkspace);
        }

        /* add OSD to frame */
        if (sink->osd != NULL && sink->osdInitialised)
        {
            if (!osd_add_to_image(sink->osd, frameInfo, (unsigned char*)frame->yuv_image->data,
                frame->yuv_image->width, frame->yuv_image->height))
            {
                ml_log_error("Failed to add OSD to frame\n");
                /* continue anyway */
            }
        }

        /* wait until it is time to display this frame */
        gettimeofday(&timeNow, NULL);
        durationSlept = 0;
        if (frameInfo->rateControl)
        {
            durationSlept = sleep_diff(frameDurationMsec * 1000, &timeNow, &sink->lastFrameTime);
        }

        /* adjust the display width/height if the window has been resized */
        windowWidth = sink->x11Common.windowWidth;
        windowHeight = sink->x11Common.windowHeight;

        scaleFactorX = windowWidth / (float)(sink->initialDisplayWidth);
        scaleFactorY = windowHeight / (float)(sink->initialDisplayHeight);
        scaleFactor = (scaleFactorX < scaleFactorY) ? scaleFactorX : scaleFactorY;

        sink->x11Common.displayWidth = sink->initialDisplayWidth * scaleFactor;
        sink->x11Common.displayHeight = sink->initialDisplayHeight * scaleFactor;


        XLockDisplay(sink->x11Common.windowInfo.display);

        if (sink->useSharedMemory)
        {
            XvShmPutImage(sink->x11Common.windowInfo.display, sink->xvport, sink->x11Common.windowInfo.window,
                sink->x11Common.windowInfo.gc, frame->yuv_image,
                0, 0, frame->yuv_image->width, frame->yuv_image->height,
                0, 0, sink->x11Common.displayWidth, sink->x11Common.displayHeight,
                False);
        }
        else
        {
            XvPutImage(sink->x11Common.windowInfo.display, sink->xvport, sink->x11Common.windowInfo.window,
                sink->x11Common.windowInfo.gc, frame->yuv_image,
                0, 0, frame->yuv_image->width, frame->yuv_image->height,
                0, 0, sink->x11Common.displayWidth, sink->x11Common.displayHeight);
        }

        XSync(sink->x11Common.windowInfo.display, False);

        XUnlockDisplay(sink->x11Common.windowInfo.display);


        x11c_process_events(&sink->x11Common);


        /* report that a new frame has been displayed */
        msl_frame_displayed(sink->listener, frameInfo);


        /* set the time that this frame was displayed */
        if (frameInfo->rateControl)
        {
            if (durationSlept < - frameSlippage)
            {
                /* reset rate control when slipped by more than frameSlippage */
                sink->lastFrameTime = timeNow;
            }
            else
            {
                /* set what the frame's display time should have been */
                requiredUsec = sink->lastFrameTime.tv_sec * 1000000 + sink->lastFrameTime.tv_usec + frameDurationMsec * 1000;
                sink->lastFrameTime.tv_usec = requiredUsec % 1000000;
                sink->lastFrameTime.tv_sec = requiredUsec / 1000000;
            }
        }
        else
        {
            gettimeofday(&sink->lastFrameTime, NULL);
        }
    }
    else
    {
        gettimeofday(&sink->lastFrameTime, NULL);
    }


    reset_streams(frame);

    return 1;
}