block_t *screen_Capture( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; screen_data_t *p_data = ( screen_data_t * )p_sys->p_data; block_t *p_block; int i_size; i_size = p_sys->fmt.video.i_height * p_sys->fmt.video.i_width * 4; if( !( p_block = block_Alloc( i_size ) ) ) { msg_Warn( p_demux, "cannot get block" ); return NULL; } CGPoint cursor_pos; CGError cursor_result; cursor_pos.x = 0; cursor_pos.y = 0; cursor_result = CGSGetCurrentCursorLocation( p_data->connection, &cursor_pos ); cursor_pos.x -= p_data->screen_left; cursor_pos.y -= p_data->screen_top; if( p_sys->b_follow_mouse && cursor_result == kCGErrorSuccess ) { FollowMouse( p_sys, cursor_pos.x, cursor_pos.y ); } screen_CaptureScreen( p_sys ); CGLSetCurrentContext( p_data->clipped ); glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT ); glDrawPixels( p_data->width, p_data->height, GL_RGBA, GL_UNSIGNED_BYTE, p_data->screen_image ); if( cursor_result == kCGErrorSuccess ) { screen_DrawCursor( p_sys, &cursor_pos ); } glReadPixels( 0, 0, p_data->width, p_data->height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, p_block->p_buffer ); return p_block; }
block_t *screen_Capture( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; screen_data_t *p_data = p_sys->p_data; if( !p_data->i_fragment ) { if( !( p_data->p_block = CaptureBlockNew( p_demux ) ) ) { msg_Warn( p_demux, "cannot get block" ); return NULL; } } if( p_sys->b_follow_mouse ) { POINT pos; GetCursorPos( &pos ); FollowMouse( p_sys, pos.x, pos.y ); } if( !BitBlt( p_data->hdc_dst, 0, p_data->i_fragment * p_data->i_fragment_size, p_sys->fmt.video.i_width, p_data->i_fragment_size, p_data->hdc_src, p_sys->i_left, p_sys->i_top + p_data->i_fragment * p_data->i_fragment_size, SRCCOPY | CAPTUREBLT ) ) { msg_Err( p_demux, "error during BitBlt()" ); return NULL; } p_data->i_fragment++; if( !( p_data->i_fragment % (p_sys->fmt.video.i_height/p_data->i_fragment_size) ) ) { block_t *p_block = p_data->p_block; p_data->i_fragment = 0; p_data->p_block = 0; if( p_sys->p_mouse ) { POINT pos; GetCursorPos( &pos ); RenderCursor( p_demux, pos.x, pos.y, p_block->p_buffer ); } return p_block; } return NULL; }
block_t *screen_Capture(demux_t *p_demux) { demux_sys_t *p_sys = p_demux->p_sys; screen_data_t *p_data = (screen_data_t *)p_sys->p_data; block_t *p_block; CGRect capture_rect; CGImageRef image; /* forward cursor location */ CGPoint cursor_pos; CGEventRef event = CGEventCreate(NULL); cursor_pos = CGEventGetLocation(event); CFRelease(event); cursor_pos.x -= p_data->screen_left; cursor_pos.y -= p_data->screen_top; if (p_sys->b_follow_mouse) FollowMouse(p_sys, cursor_pos.x, cursor_pos.y); capture_rect.origin.x = p_sys->i_left; capture_rect.origin.y = p_sys->i_top; capture_rect.size.width = p_data->width; capture_rect.size.height = p_data->height; /* fetch image data */ image = CGDisplayCreateImageForRect(p_data->display_id, capture_rect); if (!image) { msg_Warn(p_demux, "no image!"); return NULL; } /* create offscreen context */ if (!p_data->offscreen_context) { CGColorSpaceRef colorspace; colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); p_data->offscreen_bitmap_size = p_sys->fmt.video.i_width * p_sys->fmt.video.i_height * 4; p_data->offscreen_bitmap = calloc(1, p_data->offscreen_bitmap_size); if (p_data->offscreen_bitmap == NULL) { msg_Warn(p_demux, "can't allocate offscreen bitmap"); CFRelease(image); return NULL; } p_data->offscreen_context = CGBitmapContextCreate(p_data->offscreen_bitmap, p_sys->fmt.video.i_width, p_sys->fmt.video.i_height, 8, p_sys->fmt.video.i_width * 4, colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little); if (!p_data->offscreen_context) { msg_Warn(p_demux, "can't create offscreen bitmap context"); CFRelease(image); return NULL; } CGColorSpaceRelease(colorspace); p_data->offscreen_rect = CGRectMake(0, 0, p_sys->fmt.video.i_width, p_sys->fmt.video.i_height); } /* fetch cursor image */ CGImageRef cursor_image; int cid = CGSMainConnectionID(); CGPoint outHotSpot; cursor_image = CGSCreateRegisteredCursorImage(cid, (char *)"com.apple.coregraphics.GlobalCurrent", &outHotSpot); /* draw screen image and cursor image */ CGRect cursor_rect; cursor_rect.size.width = CGImageGetWidth(cursor_image); cursor_rect.size.height = CGImageGetHeight(cursor_image); cursor_rect.origin.x = cursor_pos.x - p_sys->i_left - outHotSpot.x; cursor_rect.origin.y = p_data->offscreen_rect.size.height - (cursor_pos.y + cursor_rect.size.height - p_sys->i_top - outHotSpot.y); CGContextDrawImage(p_data->offscreen_context, p_data->offscreen_rect, image); CGContextDrawImage(p_data->offscreen_context, cursor_rect, cursor_image); /* build block */ p_block = block_Alloc(p_data->offscreen_bitmap_size); if (!p_block) { msg_Warn(p_demux, "can't get block"); CFRelease(image); return NULL; } memmove(p_block->p_buffer, p_data->offscreen_bitmap, p_data->offscreen_bitmap_size); CFRelease(image); return p_block; }
block_t *screen_Capture( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; screen_data_t *p_data = ( screen_data_t * )p_sys->p_data; block_t *p_block; int i_size; i_size = p_sys->fmt.video.i_height * p_sys->fmt.video.i_width * 4; if( !( p_block = block_New( p_demux, i_size ) ) ) { msg_Warn( p_demux, "cannot get block" ); return NULL; } CGPoint cursor_pos; CGError cursor_result; cursor_pos.x = 0; cursor_pos.y = 0; cursor_result = CGSGetCurrentCursorLocation( p_data->connection, &cursor_pos ); if( p_sys->b_follow_mouse && cursor_result == kCGErrorSuccess ) { FollowMouse( p_sys, cursor_pos.x, cursor_pos.y ); p_data->left = p_sys->i_left; p_data->top = p_sys->i_top; } CGLSetCurrentContext( p_data->screen ); glReadPixels( p_data->left, p_data->screen_height - p_data->top - p_data->src_height, p_data->src_width, p_data->src_height, GL_RGBA, GL_UNSIGNED_BYTE, p_data->texture_image ); CGLSetCurrentContext( p_data->scaled ); glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, p_data->texture ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, p_data->src_width, p_data->src_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, p_data->texture_image ); glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT ); glColor3f( 1.0f, 1.0f, 1.0f ); glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, p_data->texture ); glBegin( GL_POLYGON ); glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, -1.0 ); glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, -1.0 ); glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, 1.0 ); glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, 1.0 ); glEnd(); glDisable( GL_TEXTURE_2D ); int size; int tmp1, tmp2, tmp3, tmp4; unsigned char *cursor_image; CGRect cursor_rect; CGPoint cursor_hot; if( cursor_result == kCGErrorSuccess && CGSGetGlobalCursorDataSize( p_data->connection, &size ) == kCGErrorSuccess ) { cursor_image = ( unsigned char* )malloc( size ); if( CGSGetGlobalCursorData( p_data->connection, cursor_image, &size, &tmp1, &cursor_rect, &cursor_hot, &tmp2, &tmp3, &tmp4 ) == kCGErrorSuccess ) { glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, p_data->cursor_texture ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, ( int )( cursor_rect.size.width ), ( int )( cursor_rect.size.height ), 0, GL_RGBA, GL_UNSIGNED_BYTE, ( char * )cursor_image ); cursor_rect.origin.x = cursor_pos.x - p_data->left - cursor_hot.x; cursor_rect.origin.y = cursor_pos.y - p_data->top - cursor_hot.y; cursor_rect.origin.x = 2.0 * cursor_rect.origin.x / p_data->src_width - 1.0; cursor_rect.origin.y = 2.0 * cursor_rect.origin.y / p_data->src_height - 1.0; cursor_rect.size.width = 2.0 * cursor_rect.size.width / p_data->src_width; cursor_rect.size.height = 2.0 * cursor_rect.size.height / p_data->src_height; glColor3f( 1.0f, 1.0f, 1.0f ); glEnable( GL_TEXTURE_2D ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBindTexture( GL_TEXTURE_2D, p_data->cursor_texture ); glBegin( GL_POLYGON ); glTexCoord2f( 0.0, 0.0 ); glVertex2f( cursor_rect.origin.x, cursor_rect.origin.y ); glTexCoord2f( 1.0, 0.0 ); glVertex2f( cursor_rect.origin.x + cursor_rect.size.width, cursor_rect.origin.y ); glTexCoord2f( 1.0, 1.0 ); glVertex2f( cursor_rect.origin.x + cursor_rect.size.width, cursor_rect.origin.y + cursor_rect.size.height ); glTexCoord2f( 0.0, 1.0 ); glVertex2f( cursor_rect.origin.x, cursor_rect.origin.y + cursor_rect.size.height ); glEnd(); glDisable( GL_BLEND ); glDisable( GL_TEXTURE_2D ); } free( cursor_image ); } glReadPixels( 0, 0, p_data->dest_width, p_data->dest_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, p_block->p_buffer ); return p_block; }