Пример #1
0
unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue)
{
  DISPMANX_DISPLAY_HANDLE_T display;
  DISPMANX_RESOURCE_HANDLE_T resource;
  VC_RECT_T rect;
  unsigned char *image = NULL;
  uint32_t vc_image_ptr;
  int stride;

  display = vc_dispmanx_display_open( 0 /*screen*/ );
  stride = ((width + 15) & ~15) * 4;
  image = new unsigned char [height * stride];

  if (image)
  {
    resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr );

    vc_dispmanx_snapshot(display, resource, (DISPMANX_TRANSFORM_T)0);

    vc_dispmanx_rect_set(&rect, 0, 0, width, height);
    vc_dispmanx_resource_read_data(resource, &rect, image, stride);
    vc_dispmanx_resource_delete( resource );
    vc_dispmanx_display_close(display );

    // we need to save in BGRA order so Swap RGBA -> BGRA
    if (swap_red_blue)
    {
      for (int y = 0; y < height; y++)
      {
        unsigned char *p = image + y * stride;
        for (int x = 0; x < width; x++, p+=4)
        {
          unsigned char t = p[0];
          p[0] = p[2];
          p[2] = t;
        }
      }
    }
    // assume we need to pack image if caller doesn't want stride
    if (!pstride && stride > width*4)
    {
      for (int y = 0; y < height; y++)
      {
        unsigned char *in  = image + y * stride;
        unsigned char *out = image + y * width * 4;
        memmove(out, in, width*4);
      }
    }
  }
  if (pstride)
    *pstride = stride;
  return image;
}
Пример #2
0
void save_snapshot(void)
{
  DISPMANX_DISPLAY_HANDLE_T display;
  DISPMANX_MODEINFO_T info;
  DISPMANX_RESOURCE_HANDLE_T resource;
  VC_IMAGE_TYPE_T type = VC_IMAGE_RGB888;
  VC_IMAGE_TRANSFORM_T transform = 0;
  VC_RECT_T rect;
  void *image;
  uint32_t vc_image_ptr;
  int ret;
  uint32_t screen = 0;

  fprintf(stderr,"\nWriting snapshot...\n");
  //fprintf(stderr,"Open display[%i]...\n", screen );
  display = vc_dispmanx_display_open( screen );

  ret = vc_dispmanx_display_get_info(display, &info);
  assert(ret == 0);
  //fprintf(stderr,"Display is %d x %d\n", info.width, info.height );

  image = calloc( 1, info.width * 3 * info.height );

  assert(image);

  resource = vc_dispmanx_resource_create(type, info.width, info.height,&vc_image_ptr);

  vc_dispmanx_snapshot(display, resource, transform);

  vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height);
  vc_dispmanx_resource_read_data(resource, &rect, image, info.width*3);

  char* home = getenv("HOME");
  char filename[1024];
  if (!home)
    home = "/tmp";

  snprintf(filename,sizeof(filename),"%s/pidvbip-%u.ppm",home,(unsigned int)time(NULL));
  FILE *fp = fopen(filename, "wb");
  fprintf(fp, "P6\n%d %d\n255\n", info.width, info.height);
  fwrite(image, info.width*3*info.height, 1, fp);
  fclose(fp);

  fprintf(stderr,"\nSnapshot written to %s\n",filename);

  ret = vc_dispmanx_resource_delete( resource );
  assert( ret == 0 );
  ret = vc_dispmanx_display_close(display );
  assert( ret == 0 );

  free(image);
}
int main(void)
{
    DISPMANX_DISPLAY_HANDLE_T   display;
    DISPMANX_MODEINFO_T         info;
    DISPMANX_RESOURCE_HANDLE_T  resource;
    VC_IMAGE_TYPE_T type = VC_IMAGE_RGB888;
    VC_IMAGE_TRANSFORM_T   transform = 0;
    VC_RECT_T         rect;

    void                       *image;
    uint32_t                    vc_image_ptr;

    int                   ret;

    uint32_t        screen = 0;

    bcm_host_init();

    printf("Open display[%i]...\n", screen );
    display = vc_dispmanx_display_open( screen );

    ret = vc_dispmanx_display_get_info(display, &info);
    assert(ret == 0);
    printf( "Display is %d x %d\n", info.width, info.height );

    image = calloc( 1, info.width * 3 * info.height );

    assert(image);

    resource = vc_dispmanx_resource_create( type,
                                                  info.width,
                                                  info.height,
                                                  &vc_image_ptr );

    vc_dispmanx_snapshot(display, resource, transform);

    vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height);
    vc_dispmanx_resource_read_data(resource, &rect, image, info.width*3); 

    FILE *fp = fopen("out.ppm", "wb");
    fprintf(fp, "P6\n%d %d\n255\n", info.width, info.height);
    fwrite(image, info.width*3*info.height, 1, fp);
    fclose(fp);

    ret = vc_dispmanx_resource_delete( resource );
    assert( ret == 0 );
    ret = vc_dispmanx_display_close(display );
    assert( ret == 0 );

    return 0;
}
Пример #4
0
Файл: RBP.cpp Проект: Cygne/xbmc
unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue, bool video_only)
{
  DISPMANX_DISPLAY_HANDLE_T display;
  DISPMANX_RESOURCE_HANDLE_T resource;
  VC_RECT_T rect;
  unsigned char *image = NULL;
  uint32_t vc_image_ptr;
  int stride;
  uint32_t flags = 0;

  if (video_only)
    flags |= DISPMANX_SNAPSHOT_NO_RGB|DISPMANX_SNAPSHOT_FILL;
  if (swap_red_blue)
    flags |= DISPMANX_SNAPSHOT_SWAP_RED_BLUE;
  if (!pstride)
    flags |= DISPMANX_SNAPSHOT_PACK;

  display = vc_dispmanx_display_open( 0 /*screen*/ );
  stride = ((width + 15) & ~15) * 4;
  image = new unsigned char [height * stride];

  if (image)
  {
    resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr );

    vc_dispmanx_snapshot(display, resource, (DISPMANX_TRANSFORM_T)flags);

    vc_dispmanx_rect_set(&rect, 0, 0, width, height);
    vc_dispmanx_resource_read_data(resource, &rect, image, stride);
    vc_dispmanx_resource_delete( resource );
    vc_dispmanx_display_close(display );
  }
  if (pstride)
    *pstride = stride;
  return image;
}
Пример #5
0
int main(int argc, char **argv)
{
	DISPMANX_DISPLAY_HANDLE_T main_display_handle;
	DISPMANX_RESOURCE_HANDLE_T screen_resource_handle;
	
	VC_RECT_T rectangle;
	
	int ret;
	uint32_t image_prt;
	uint16_t image[2][ PICTURE_PIXELS ];
	uint32_t current_frame = 0, old_frame=1;
	uint32_t i, x, y, start, end, count;
	uint16_t *p_current_frame, *p_old_frame, *p_start;
		
	bcm_host_init();
	
	if ( !bcm2835_init() )
	return ( -1 );
	
	TFT_init_board();
	
	TFT_hard_reset();
	
	RAIO_init();

	//clear old image 
	p_old_frame     = &image[ old_frame ][0];
	for(x=0; x<76800; x++)
	{
		*p_old_frame++ = 0x1111;
	}
	
	
	// open main framebuffer device
	main_display_handle = vc_dispmanx_display_open( 0 );
    if ( !main_display_handle )
    {
        printf("\n Unable to open primary display");
        return( -1 );
    }
    
    // now build up the shadow area for RAIO
    screen_resource_handle = vc_dispmanx_resource_create( VC_IMAGE_RGB565, DISPLAY_WIDTH, DISPLAY_HEIGHT, &image_prt );       
    if ( !screen_resource_handle )
    {
        printf("\n Unable to create screen buffer");
        vc_dispmanx_display_close( main_display_handle );
        return ( -1 );
    }

	vc_dispmanx_rect_set( &rectangle, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT );    
    
    while( 1 )
    {    
		ret = vc_dispmanx_snapshot( main_display_handle, screen_resource_handle, DISPMANX_NO_ROTATE );  
    
		vc_dispmanx_resource_read_data( screen_resource_handle, &rectangle, &image[ current_frame ][0], DISPLAY_WIDTH*2 ); 

		
		i=0;
		p_current_frame = &image[ current_frame ][ 0 ];
		p_old_frame     = &image[ old_frame ][ 0 ];	
		
		while (i<PICTURE_PIXELS)
		{		
			while (( *p_current_frame == *p_old_frame) && (i<PICTURE_PIXELS) )
			{
				p_current_frame++;
				p_old_frame++;
				i = i+1;
			}
			p_start = p_current_frame;
			start = i;
			
			
			while (( *p_current_frame != *p_old_frame) && (i<PICTURE_PIXELS) )
			{
				p_current_frame++;
				p_old_frame++;
				i = i+1;
			}
			count = i - start;
			
			y=start/DISPLAY_WIDTH;
			x=start-y*DISPLAY_WIDTH;
			RAIO_set_cursor( x, y );
			RAIO_Write_Picture( p_start, count );				
		}
		
		
		old_frame = current_frame;
		if ( current_frame == 0 )
			current_frame = 1;
		else
			current_frame = 0;
			
			
		// 100ms -> 10 fps
		usleep( 100 * 1000 );
	
	}


	return ( 0 );
}
Пример #6
0
int process() {
    DISPMANX_DISPLAY_HANDLE_T display;
    DISPMANX_MODEINFO_T display_info;
    DISPMANX_RESOURCE_HANDLE_T screen_resource;
    VC_IMAGE_TRANSFORM_T transform;
    uint32_t image_prt;
    VC_RECT_T rect1;
    int ret;
    int fbfd = 0;
    char *fbp = 0;

    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;


    bcm_host_init();

    display = vc_dispmanx_display_open(0);
    if (!display) {
        syslog(LOG_ERR, "Unable to open primary display");
        return -1;
    }
    ret = vc_dispmanx_display_get_info(display, &display_info);
    if (ret) {
        syslog(LOG_ERR, "Unable to get primary display information");
        return -1;
    }
    syslog(LOG_INFO, "Primary display is %d x %d", display_info.width, display_info.height);


    fbfd = open("/dev/fb1", O_RDWR);
    if (!fbfd) {
        syslog(LOG_ERR, "Unable to open secondary display");
        return -1;
    }
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
        syslog(LOG_ERR, "Unable to get secondary display information");
        return -1;
    }
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
        syslog(LOG_ERR, "Unable to get secondary display information");
        return -1;
    }

    syslog(LOG_INFO, "Second display is %d x %d %dbps\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

    screen_resource = vc_dispmanx_resource_create(VC_IMAGE_RGB565, vinfo.xres, vinfo.yres, &image_prt);
    if (!screen_resource) {
        syslog(LOG_ERR, "Unable to create screen buffer");
        close(fbfd);
        vc_dispmanx_display_close(display);
        return -1;
    }

    fbp = (char*) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if (fbp <= 0) {
        syslog(LOG_ERR, "Unable to create mamory mapping");
        close(fbfd);
        ret = vc_dispmanx_resource_delete(screen_resource);
        vc_dispmanx_display_close(display);
        return -1;
    }

    vc_dispmanx_rect_set(&rect1, 0, 0, vinfo.xres, vinfo.yres);

    while (1) {
        ret = vc_dispmanx_snapshot(display, screen_resource, 0);
        vc_dispmanx_resource_read_data(screen_resource, &rect1, fbp, vinfo.xres * vinfo.bits_per_pixel / 8);
        usleep(25 * 1000);
    }

    munmap(fbp, finfo.smem_len);
    close(fbfd);
    ret = vc_dispmanx_resource_delete(screen_resource);
    vc_dispmanx_display_close(display);
}
Пример #7
0
/*
* simulate grabbing a picture from some device
*/
int TakePicture(unsigned char *buffer)
{
	static int last_line=0, fps=0, fcount=0;
	int line=0;
	int i,j;
	struct timeval now;
	int found;

	VC_IMAGE_TRANSFORM_T	transform = 0;
	VC_RECT_T			rect;

	vc_dispmanx_snapshot(display, resource, transform);

	vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height);
	vc_dispmanx_resource_read_data(resource, &rect, image, pitch); 

	unsigned short *image_p = (unsigned short *)image;
	unsigned short *buffer_p = (unsigned short *)buffer;


	// find y0, y1
	found = 0;
	unsigned short *back_image_p = (unsigned short *)back_image;
	for (i=0; i<info.height && !found; i++)
	{
		for (j = 0; j<info.width; j++) {
			if (back_image_p[i*padded_width + j] != image_p[i*padded_width + j])
			{
				r_y0 = i;
				found  = 1;		
				break;
			}
		}
	}

	found = 0;
	for (i=info.height-1; i>=r_y0 && !found; i--)
	{
		for (j = 0; j<info.width; j++) {
			if (back_image_p[i*padded_width + j] != image_p[i*padded_width + j])
			{
				r_y1 = i+1;
				found  = 1;		
				break;
			}
		}
	}

	found = 0;
	for (i=0; i<info.width && !found; i++)
	{
		for (j = r_y0; j< r_y1; j++) {
			if (back_image_p[j*padded_width + i] != image_p[j*padded_width + i])
			{
				r_x0 = i;
				found  = 1;		
				break;
			}
		}
	}

	found = 0;
	for (i=info.width-1; i>=r_x0 && !found; i--)
	{
		for (j = r_y0; j< r_y1; j++) {
			if (back_image_p[j*padded_width + i] != image_p[j*padded_width + i])
			{
				r_x1 = i+1;
				found  = 1;		
				break;
			}
		}
	}

	for(j=r_y0;j<r_y1;++j) {
		for(i=r_x0;i<r_x1;++i) {
			unsigned short	tbi = image_p[j*padded_width + i]; 

			unsigned short        R5 = (tbi >> 11); 
			unsigned short       G5 = ((tbi >> 6) & 0x1f);
			unsigned short         B5 = tbi & 0x1f;

			tbi = (B5 << 10) | (G5 << 5) | R5;

			buffer_p[j*padded_width +i] = tbi;
		}
	}

	/* swap image and back_image buffers */
	void *tmp_image = back_image;
	back_image = image;
	image = tmp_image;

	/*
	* simulate the passage of time
	*
	* draw a simple black line that moves down the screen. The faster the
	* client, the more updates it will get, the smoother it will look!
	*/
	gettimeofday(&now,NULL);
	line = now.tv_usec / (1000000/info.height);
	if (line>info.height) line=info.height-1;
	//memset(&buffer[(info.width * BPP) * line], 0, (info.width * BPP));
	/* frames per second (informational only) */
	fcount++;
	if (last_line > line) {
		fps = fcount;
		fcount = 0;
	}
	last_line = line;
	fprintf(stderr,"%03d/%03d Picture (%03d fps) ", line, info.height, fps);

	fprintf(stderr, "x0=%d, y0=%d, x1=%d, y1=%d              \r", r_x0, r_y0, r_x1, r_y1); 
	/* success!   We have a new picture! */
	return (1==1);
}
static jboolean fbDispmanRobotScreenCapture(jint x, jint y,
                                            jint width, jint height,
                                            jint *pixels) {
    FILE *fb;
    unsigned int *pixelBuffer = NULL;
    unsigned char *pixelBufferPtr = NULL;
    unsigned char *dst = (unsigned char *) pixels;
    int i = 0;
    int fbFileHandle;
    struct fb_var_screeninfo screenInfo;
    unsigned int dstByteStride = width * 4;
    VC_IMAGE_TRANSFORM_T transform = 0;
    DISPMANX_RESOURCE_HANDLE_T resource = 0;
    DISPMANX_DISPLAY_HANDLE_T display = 0;
    DISPMANX_RESOURCE_HANDLE_T screenResource = 0;
    uint32_t imagePtr;
    int rc;

    GLASS_LOG_FINE("Capture %i,%i+%ix%i", x, y, width, height);

    if (width < 1 || height < 1) {
        GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1");
        return JNI_FALSE;
    }

    GLASS_LOG_FINE("open(%s, O_RDONLY)", FB_DEVICE);
    fbFileHandle = open(FB_DEVICE, O_RDONLY);
    if (fbFileHandle < 0) {
        GLASS_LOG_SEVERE("Cannot open framebuffer");
        return JNI_FALSE;
    }

    GLASS_LOG_FINE("ioctl(%s, FBIOGET_VSCREENINFO)", FB_DEVICE);
    if (ioctl(fbFileHandle, FBIOGET_VSCREENINFO, &screenInfo)) {
        GLASS_LOG_SEVERE("Cannot get screen info");
        GLASS_LOG_FINE("close(%s)", FB_DEVICE);
        close(fbFileHandle);
        return JNI_FALSE;
    }
    GLASS_LOG_FINE("Read screen info: res=%ix%i, offset=%ix%i",
                   screenInfo.xres, screenInfo.yres,
                   screenInfo.xoffset, screenInfo.yoffset);
    GLASS_LOG_FINE("close(%s)", FB_DEVICE);
    close(fbFileHandle);

    VC_RECT_T pixelRect = { 0, 0, screenInfo.xres, screenInfo.yres };

    int pixelBufferLength = screenInfo.xres * screenInfo.yres * 4;
    pixelBuffer = (unsigned int *) malloc(pixelBufferLength);
    pixelBufferPtr = (unsigned char *) pixelBuffer;

    if (pixelBuffer == NULL) {
        printf("Failed to allocate temporary pixel buffer\n");
        return JNI_FALSE;
    }

    GLASS_LOG_FINE("fopen(%s, \"r\") to read %ix%i pixels at bit depth %i\n",
                   FB_DEVICE, width, height, screenInfo.bits_per_pixel);

    display = vc_dispmanx_display_open(0 /* LCD */);
    if (display == 0) {
        fprintf(stderr, "fbRobotScreenCapture: Dispman: Cannot open display\n");
        free(pixelBuffer);
        return JNI_FALSE;
    }

    // create the resource for the snapshot
    screenResource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, screenInfo.xres, screenInfo.yres, &imagePtr);
    if (!screenResource) {
        fprintf(stderr, "fbRobotScreenCapture: Cannot create resource\n");
        vc_dispmanx_display_close(display);
        free(pixelBuffer);
        return JNI_FALSE;
    }

    rc = vc_dispmanx_snapshot(display, screenResource, transform);
    rc = 0;
    if (rc) {
        fprintf(stderr, "fbRobotScreenCapture: snapshot failed\n");
        vc_dispmanx_display_close(display);
        free(pixelBuffer);
        return JNI_FALSE;
    }

    rc = vc_dispmanx_resource_read_data(screenResource, &pixelRect, pixelBuffer, screenInfo.xres * 4);

    if (rc) {
        fprintf(stderr, "fbRobotScreenCapture: Cannot read pixels %d\n", rc);
        vc_dispmanx_display_close(display);
        free(pixelBuffer);
        return JNI_FALSE;
    }

    rc = vc_dispmanx_resource_delete(screenResource);
    if (rc) {
        fprintf(stderr, "fbRobotScreenCapture: failed to free buffer %d\n", rc);
        vc_dispmanx_display_close(display);
        free(pixelBuffer);
        return JNI_FALSE;
    }
    screenResource = 0;

    if (x < 0) {
        pixelBuffer += -x;
        width += x;
        x = 0;
    }
    if (y < 0) {
        pixelBuffer += -y * (int)screenInfo.xres;
        height += y;
        y = 0;
    }

    int widthLimit = width;
    int heightLimit = height;

    // Required height is larger than screen's height
    if ((int) screenInfo.yres < height) {
        heightLimit = (int) screenInfo.yres;
    }
    // Required width is larger than screen's width
    if ((int) screenInfo.xres < width) {
        widthLimit = (int) screenInfo.xres;
    }
    // Required height is out of range
    if (((int) screenInfo.yres - y) < height) {
        heightLimit = (int) screenInfo.yres - y;
    }
    // Required width is out of range
    if (((int) screenInfo.xres - x) < width) {
        widthLimit = (int) screenInfo.xres - x;
    }

    if (widthLimit > 0 && heightLimit > 0) {
        // copy the relevant portion of the screen to the supplied pixel array
        int offset = y * screenInfo.xres * 4 + x * 4;
        for (i = 0; i < heightLimit; i++) {
            memcpy(dst + i * dstByteStride, pixelBufferPtr + offset, widthLimit * 4);
            offset += screenInfo.xres * 4;
        }
    } else {
        GLASS_LOG_SEVERE("Failed to take a snapshot, some of parameters are illegal");
        free(pixelBuffer);
        return JNI_FALSE;
    }

    vc_dispmanx_display_close(display);
    free(pixelBuffer);
    return JNI_TRUE;
}
Пример #9
0
int
main(
    int argc,
    char *argv[])
{
    int opt = 0;

    bool writeToStdout = false;
    char *pngName = DEFAULT_NAME;
    int32_t requestedWidth = 0;
    int32_t requestedHeight = 0;
    uint32_t displayNumber = DEFAULT_DISPLAY_NUMBER;
    int compression = Z_DEFAULT_COMPRESSION;
    int delay = DEFAULT_DELAY;

    VC_IMAGE_TYPE_T imageType = VC_IMAGE_RGBA32;
    int8_t dmxBytesPerPixel  = 4;

    int result = 0;

    program = basename(argv[0]);

    //-------------------------------------------------------------------

    char *sopts = "c:d:D:Hh:p:w:s";

    struct option lopts[] =
    {
        { "compression", required_argument, NULL, 'c' },
        { "delay", required_argument, NULL, 'd' },
        { "display", required_argument, NULL, 'D' },
        { "height", required_argument, NULL, 'h' },
        { "help", no_argument, NULL, 'H' },
        { "pngname", required_argument, NULL, 'p' },
        { "width", required_argument, NULL, 'w' },
        { "stdout", no_argument, NULL, 's' },
        { NULL, no_argument, NULL, 0 }
    };

    while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1)
    {
        switch (opt)
        {
        case 'c':

            compression = atoi(optarg);

            if ((compression < 0) || (compression > 9))
            {
                compression = Z_DEFAULT_COMPRESSION;
            }

            break;

        case 'd':

            delay = atoi(optarg);
            break;

        case 'D':

            displayNumber = atoi(optarg);
            break;

        case 'h':

            requestedHeight = atoi(optarg);
            break;

        case 'p':

            pngName = optarg;
            break;

        case 'w':

            requestedWidth = atoi(optarg);
            break;

        case 's':

            writeToStdout = true;
            break;

        case 'H':
        default:

            usage();

            if (opt == 'H')
            {
                exit(EXIT_SUCCESS);
            }
            else
            {
                exit(EXIT_FAILURE);
            }

            break;
        }
    }

    //-------------------------------------------------------------------

    bcm_host_init();

    //-------------------------------------------------------------------
    //
    // When the display is rotate (either 90 or 270 degrees) we need to
    // swap the width and height of the snapshot
    //

    char response[1024];
    int displayRotated = 0;

    if (vc_gencmd(response, sizeof(response), "get_config int") == 0)
    {
        vc_gencmd_number_property(response,
                                  "display_rotate",
                                  &displayRotated);
    }

    //-------------------------------------------------------------------

    if (delay)
    {
        sleep(delay);
    }

    //-------------------------------------------------------------------

    DISPMANX_DISPLAY_HANDLE_T displayHandle
        = vc_dispmanx_display_open(displayNumber);

    if (displayHandle == 0)
    {
        fprintf(stderr,
                "%s: unable to open display %d\n",
                program,
                displayNumber);

        exit(EXIT_FAILURE);
    }

    DISPMANX_MODEINFO_T modeInfo;
    result = vc_dispmanx_display_get_info(displayHandle, &modeInfo);

    if (result != 0)
    {
        fprintf(stderr, "%s: unable to get display information\n", program);
        exit(EXIT_FAILURE);
    }

    int32_t pngWidth = modeInfo.width;
    int32_t pngHeight = modeInfo.height;

    if (requestedWidth > 0)
    {
        pngWidth = requestedWidth;

        if (requestedHeight == 0)
        {
            double numerator = modeInfo.height * requestedWidth;
            double denominator = modeInfo.width;

            pngHeight = (int32_t)ceil(numerator / denominator);
        }
    }

    if (requestedHeight > 0)
    {
        pngHeight = requestedHeight;

        if (requestedWidth == 0)
        {
            double numerator = modeInfo.width * requestedHeight;
            double denominator = modeInfo.height;

            pngWidth = (int32_t)ceil(numerator / denominator);
        }
    }

    //-------------------------------------------------------------------
    // only need to check low bit of displayRotated (value of 1 or 3).
    // If the display is rotated either 90 or 270 degrees (value 1 or 3)
    // the width and height need to be transposed.

    int32_t dmxWidth = pngWidth;
    int32_t dmxHeight = pngHeight;

    if (displayRotated & 1)
    {
        dmxWidth = pngHeight;
        dmxHeight = pngWidth;
    }

    int32_t dmxPitch = dmxBytesPerPixel * ALIGN_TO_16(dmxWidth);

    void *dmxImagePtr = malloc(dmxPitch * dmxHeight);

    if (dmxImagePtr == NULL)
    {
        fprintf(stderr, "%s: unable to allocated image buffer\n", program);
        exit(EXIT_FAILURE);
    }

    //-------------------------------------------------------------------

    uint32_t vcImagePtr = 0;
    DISPMANX_RESOURCE_HANDLE_T resourceHandle;
    resourceHandle = vc_dispmanx_resource_create(imageType,
                                                 dmxWidth,
                                                 dmxHeight,
                                                 &vcImagePtr);

    result = vc_dispmanx_snapshot(displayHandle,
                                  resourceHandle,
                                  DISPMANX_NO_ROTATE);

    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr, "%s: vc_dispmanx_snapshot() failed\n", program);
        exit(EXIT_FAILURE);
    }

    VC_RECT_T rect;
    result = vc_dispmanx_rect_set(&rect, 0, 0, dmxWidth, dmxHeight);

    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr, "%s: vc_dispmanx_rect_set() failed\n", program);
        exit(EXIT_FAILURE);
    }

    result = vc_dispmanx_resource_read_data(resourceHandle,
                                            &rect,
                                            dmxImagePtr,
                                            dmxPitch);


    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr,
                "%s: vc_dispmanx_resource_read_data() failed\n",
                program);

        exit(EXIT_FAILURE);
    }

    vc_dispmanx_resource_delete(resourceHandle);
    vc_dispmanx_display_close(displayHandle);

    //-------------------------------------------------------------------
    // Convert from RGBA (32 bit) to RGB (24 bit)

    int8_t pngBytesPerPixel = 3;
    int32_t pngPitch = pngBytesPerPixel * pngWidth;
    void *pngImagePtr = malloc(pngPitch * pngHeight);

    int32_t j = 0;
    for (j = 0 ; j < pngHeight ; j++)
    {
        int32_t dmxXoffset = 0;
        int32_t dmxYoffset = 0;

        switch (displayRotated & 3)
        {
        case 0: // 0 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxYoffset = (dmxHeight - j - 1) * dmxPitch;
            }
            else
            {
                dmxYoffset = j * dmxPitch;
            }

            break;

        case 1: // 90 degrees


            if (displayRotated & 0x20000) // flip vertical
            {
                dmxXoffset = j * dmxBytesPerPixel;
            }
            else
            {
                dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel;
            }

            break;

        case 2: // 180 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxYoffset = j * dmxPitch;
            }
            else
            {
                dmxYoffset = (dmxHeight - j - 1) * dmxPitch;
            }

            break;

        case 3: // 270 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel;
            }
            else
            {
                dmxXoffset = j * dmxBytesPerPixel;
            }

            break;
        }

        int32_t i = 0;
        for (i = 0 ; i < pngWidth ; i++)
        {
            uint8_t *pngPixelPtr = pngImagePtr
                                 + (i * pngBytesPerPixel)
                                 + (j * pngPitch);

            switch (displayRotated & 3)
            {
            case 0: // 0 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel;
                }
                else
                {
                    dmxXoffset = i * dmxBytesPerPixel;
                }

                break;

            case 1: // 90 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxYoffset = (dmxHeight - i - 1) * dmxPitch;
                }
                else
                {
                    dmxYoffset = i * dmxPitch;
                }

                break;

            case 2: // 180 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxXoffset = i * dmxBytesPerPixel;
                }
                else
                {
                    dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel;
                }

                break;

            case 3: // 270 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxYoffset = i * dmxPitch;
                }
                else
                {
                    dmxYoffset = (dmxHeight - i - 1) * dmxPitch;
                }

                break;
            }

            uint8_t *dmxPixelPtr = dmxImagePtr + dmxXoffset + dmxYoffset;

            memcpy(pngPixelPtr, dmxPixelPtr, 3);
        }
    }

    free(dmxImagePtr);
    dmxImagePtr = NULL;

    //-------------------------------------------------------------------

    png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                 NULL,
                                                 NULL,
                                                 NULL);

    if (pngPtr == NULL)
    {
        fprintf(stderr,
                "%s: unable to allocated PNG write structure\n",
                program);

        exit(EXIT_FAILURE);
    }

    png_infop infoPtr = png_create_info_struct(pngPtr);

    if (infoPtr == NULL)
    {
        fprintf(stderr,
                "%s: unable to allocated PNG info structure\n",
                program);

        exit(EXIT_FAILURE);
    }

    if (setjmp(png_jmpbuf(pngPtr)))
    {
        fprintf(stderr, "%s: unable to create PNG\n", program);
        exit(EXIT_FAILURE);
    }

    FILE *pngfp = NULL;

    if (writeToStdout)
    {
        pngfp = stdout;
    }
    else
    {
        pngfp = fopen(pngName, "wb");

        if (pngfp == NULL)
        {
            fprintf(stderr,
                    "%s: unable to create %s - %s\n",
                    program,
                    pngName,
                    strerror(errno));

            exit(EXIT_FAILURE);
        }
    }

    png_init_io(pngPtr, pngfp);

    png_set_IHDR(
        pngPtr,
        infoPtr,
        pngWidth,
        pngHeight,
        8,
        PNG_COLOR_TYPE_RGB,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_BASE,
        PNG_FILTER_TYPE_BASE);

    if (compression != Z_DEFAULT_COMPRESSION)
    {
        png_set_compression_level(pngPtr, compression);
    }

    png_write_info(pngPtr, infoPtr);

    int y = 0;
    for (y = 0; y < pngHeight; y++)
    {
        png_write_row(pngPtr, pngImagePtr + (pngPitch * y));
    }

    png_write_end(pngPtr, NULL);
    png_destroy_write_struct(&pngPtr, &infoPtr);

    if (pngfp != stdout)
    {
        fclose(pngfp);
    }

    //-------------------------------------------------------------------

    free(pngImagePtr);
    pngImagePtr = NULL;

    return 0;
}
Пример #10
0
		void Copy()
		{
			vc_dispmanx_snapshot(display, screen_resource, (DISPMANX_TRANSFORM_T)0);
			vc_dispmanx_resource_read_data(screen_resource, &rect1, fbp, vinfo.xres * vinfo.bits_per_pixel / 8);
		}
Пример #11
0
static bool recreate_dispmanx(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    int display_nr = 0;
    int layer = 0;

    MP_VERBOSE(ctx, "Recreating DISPMANX state...\n");

    destroy_dispmanx(ctx);

    p->display = vc_dispmanx_display_open(display_nr);
    p->update = vc_dispmanx_update_start(0);
    if (!p->display || !p->update) {
        MP_FATAL(ctx, "Could not get DISPMANX objects.\n");
        goto fail;
    }

    uint32_t dispw, disph;
    if (graphics_get_display_size(0, &dispw, &disph) < 0) {
        MP_FATAL(ctx, "Could not get display size.\n");
        goto fail;
    }
    p->w = dispw;
    p->h = disph;

    if (ctx->vo->opts->fullscreen) {
        p->x = p->y = 0;
    } else {
        struct vo_win_geometry geo;
        struct mp_rect screenrc = {0, 0, p->w, p->h};

        vo_calc_window_geometry(ctx->vo, &screenrc, &geo);

        mp_rect_intersection(&geo.win, &screenrc);

        p->x = geo.win.x0;
        p->y = geo.win.y0;
        p->w = geo.win.x1 - geo.win.x0;
        p->h = geo.win.y1 - geo.win.y0;
    }

    // dispmanx is like a neanderthal version of Wayland - you can add an
    // overlay any place on the screen.
    VC_RECT_T dst = {.x = p->x, .y = p->y, .width = p->w, .height = p->h};
    VC_RECT_T src = {.width = p->w << 16, .height = p->h << 16};
    VC_DISPMANX_ALPHA_T alpha = {
        .flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE,
        .opacity = 0xFF,
    };
    p->window = vc_dispmanx_element_add(p->update, p->display, layer, &dst, 0,
                                        &src, DISPMANX_PROTECTION_NONE, &alpha,
                                        0, 0);
    if (!p->window) {
        MP_FATAL(ctx, "Could not add DISPMANX element.\n");
        goto fail;
    }

    vc_dispmanx_update_submit_sync(p->update);
    p->update = vc_dispmanx_update_start(0);

    p->egl_window = (EGL_DISPMANX_WINDOW_T){
        .element = p->window,
        .width = p->w,
        .height = p->h,
    };
    p->egl_surface = eglCreateWindowSurface(p->egl_display, p->egl_config,
                                            &p->egl_window, NULL);

    if (p->egl_surface == EGL_NO_SURFACE) {
        MP_FATAL(ctx, "Could not create EGL surface!\n");
        goto fail;
    }

    if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface,
                        p->egl_context))
    {
        MP_FATAL(ctx, "Failed to set context!\n");
        goto fail;
    }

    p->display_fps = 0;
    TV_GET_STATE_RESP_T tvstate;
    TV_DISPLAY_STATE_T tvstate_disp;
    if (!vc_tv_get_state(&tvstate) && !vc_tv_get_display_state(&tvstate_disp)) {
        if (tvstate_disp.state & (VC_HDMI_HDMI | VC_HDMI_DVI)) {
            p->display_fps = tvstate_disp.display.hdmi.frame_rate;

            HDMI_PROPERTY_PARAM_T param = {
                .property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE,
            };
            if (!vc_tv_hdmi_get_property(&param) &&
                param.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC)
                p->display_fps = p->display_fps / 1.001;
        } else {
            p->display_fps = tvstate_disp.display.sdtv.frame_rate;
        }
    }

    p->win_params[0] = display_nr;
    p->win_params[1] = layer;
    p->win_params[2] = p->x;
    p->win_params[3] = p->y;

    ctx->vo->dwidth = p->w;
    ctx->vo->dheight = p->h;
    ra_gl_ctx_resize(ctx->swapchain, p->w, p->h, 0);

    ctx->vo->want_redraw = true;

    vo_event(ctx->vo, VO_EVENT_WIN_STATE);
    return true;

fail:
    destroy_dispmanx(ctx);
    return false;
}

static void rpi_swap_buffers(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    eglSwapBuffers(p->egl_display, p->egl_surface);
}

static bool rpi_init(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);

    bcm_host_init();

    vc_tv_register_callback(tv_callback, ctx);

    p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (!eglInitialize(p->egl_display, NULL, NULL)) {
        MP_FATAL(ctx, "EGL failed to initialize.\n");
        goto fail;
    }

    if (!mpegl_create_context(ctx, p->egl_display, &p->egl_context, &p->egl_config))
        goto fail;

    if (recreate_dispmanx(ctx) < 0)
        goto fail;

    mpegl_load_functions(&p->gl, ctx->log);

    struct ra_gl_ctx_params params = {
        .swap_buffers = rpi_swap_buffers,
        .native_display_type = "MPV_RPI_WINDOW",
        .native_display = p->win_params,
    };

    if (!ra_gl_ctx_init(ctx, &p->gl, params))
        goto fail;

    return true;

fail:
    rpi_uninit(ctx);
    return false;
}

static bool rpi_reconfig(struct ra_ctx *ctx)
{
    return recreate_dispmanx(ctx);
}

static struct mp_image *take_screenshot(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;

    if (!p->display)
        return NULL;

    struct mp_image *img = mp_image_alloc(IMGFMT_BGR0, p->w, p->h);
    if (!img)
        return NULL;

    DISPMANX_RESOURCE_HANDLE_T resource =
        vc_dispmanx_resource_create(VC_IMAGE_ARGB8888,
                                    img->w | ((img->w * 4) << 16), img->h,
                                    &(int32_t){0});
    if (!resource)
        goto fail;

    if (vc_dispmanx_snapshot(p->display, resource, 0))
        goto fail;

    VC_RECT_T rc = {.width = img->w, .height = img->h};
    if (vc_dispmanx_resource_read_data(resource, &rc, img->planes[0], img->stride[0]))
        goto fail;

    vc_dispmanx_resource_delete(resource);
    return img;

fail:
    vc_dispmanx_resource_delete(resource);
    talloc_free(img);
    return NULL;
}

static int rpi_control(struct ra_ctx *ctx, int *events, int request, void *arg)
{
    struct priv *p = ctx->priv;

    switch (request) {
    case VOCTRL_SCREENSHOT_WIN:
        *(struct mp_image **)arg = take_screenshot(ctx);
        return VO_TRUE;
    case VOCTRL_FULLSCREEN:
        recreate_dispmanx(ctx);
        return VO_TRUE;
    case VOCTRL_CHECK_EVENTS:
        if (atomic_fetch_and(&p->reload_display, 0)) {
            MP_WARN(ctx, "Recovering from display mode switch...\n");
            recreate_dispmanx(ctx);
        }
        return VO_TRUE;
    case VOCTRL_GET_DISPLAY_FPS:
        *(double *)arg = p->display_fps;
        return VO_TRUE;
    }

    return VO_NOTIMPL;
}

const struct ra_ctx_fns ra_ctx_rpi = {
    .type           = "opengl",
    .name           = "rpi",
    .reconfig       = rpi_reconfig,
    .control        = rpi_control,
    .init           = rpi_init,
    .uninit         = rpi_uninit,
};
Пример #12
0
int main(int argc, char *argv[]) {
    int quality = 75;
    if (argc == 2) {
        quality = atoi(argv[1]);
        if (quality < 10 || quality > 100) {
            fprintf(stderr, "invalid quality. must be between 10 and 100\n");
            return 1;
        }
    }

    bcm_host_init();

    uint32_t screen = 0;

    DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(screen);
    DISPMANX_MODEINFO_T info;

    int ret = vc_dispmanx_display_get_info(display, &info);
    assert(ret == 0);

    /* DispmanX expects buffer rows to be aligned to a 32 bit boundary */
    int pitch = ALIGN_UP(2 * info.width, 32);

    uint32_t vc_image_ptr;
    VC_IMAGE_TYPE_T type = VC_IMAGE_RGB565;
    DISPMANX_RESOURCE_HANDLE_T resource = vc_dispmanx_resource_create(
        type, info.width, info.height, &vc_image_ptr
    );
    
    VC_IMAGE_TRANSFORM_T transform = 0;
    vc_dispmanx_snapshot(display, resource, transform);

    VC_RECT_T rect;
    vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height);

    unsigned char *image = malloc(pitch * info.height);
    assert(image);
    vc_dispmanx_resource_read_data(resource, &rect, image, info.width * 2);

    ret = vc_dispmanx_resource_delete(resource);
    assert(ret == 0);

    ret = vc_dispmanx_display_close(display);
    assert(ret == 0);

    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_pointer[1];

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, stdout);

    cinfo.image_width = info.width;
    cinfo.image_height = info.height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, quality, TRUE);
    jpeg_start_compress(&cinfo, TRUE);

    int row_stride = cinfo.image_width * 3;
    while (cinfo.next_scanline < cinfo.image_height) {
        unsigned char row[row_stride];
        unsigned char *dst = &row[0];
        uint16_t *src = (uint16_t*)(image + pitch * cinfo.next_scanline);
        for (int x = 0; x < cinfo.image_width; x++, src++) {
            *dst++ = ((*src & 0xf800) >> 11) << 3;
            *dst++ = ((*src & 0x07e0) >>  5) << 2;
            *dst++ = ((*src & 0x001f) >>  0) << 3;
        }
        row_pointer[0] = row;
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
    return 0;
}
Пример #13
0
void DMXResource::ReadData(VC_RECT_T& rect, void *image, int pitch)
{
	vc_dispmanx_resource_read_data(m_resource, &rect, image, pitch);
}