[vlc-commits] screen/mac: cursor rendering

FUJISAWA Tooru git at videolan.org
Tue Feb 26 23:04:45 CET 2013


vlc | branch: master | FUJISAWA Tooru <arai_a at mac.com> | Tue Feb 26 21:28:41 2013 +0900| [89d1b53d2aed6046d22d6bf890750ea3e8000820] | committer: Felix Paul Kühne

screen/mac: cursor rendering

Signed-off-by: Felix Paul Kühne <fkuehne at videolan.org>

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=89d1b53d2aed6046d22d6bf890750ea3e8000820
---

 modules/access/screen/mac.c |  146 +++++++++++++++++++++----------------------
 1 file changed, 71 insertions(+), 75 deletions(-)

diff --git a/modules/access/screen/mac.c b/modules/access/screen/mac.c
index 09dd7b1..698e362 100644
--- a/modules/access/screen/mac.c
+++ b/modules/access/screen/mac.c
@@ -56,6 +56,11 @@ struct screen_data_t
     int screen_height;
 
     CGDirectDisplayID display_id;
+
+    CGContextRef offscreen_context;
+    CGRect offscreen_rect;
+    void *offscreen_bitmap;
+    size_t offscreen_bitmap_size;
 };
 
 int screen_InitCapture(demux_t *p_demux)
@@ -63,7 +68,6 @@ int screen_InitCapture(demux_t *p_demux)
     demux_sys_t *p_sys = p_demux->p_sys;
     screen_data_t *p_data;
     CGLError returnedError;
-    int i_bits_per_pixel, i_chroma = 0;
 
     p_sys->p_data = p_data = calloc(1, sizeof(screen_data_t));
     if (!p_data)
@@ -106,59 +110,17 @@ int screen_InitCapture(demux_t *p_demux)
         p_data->height = p_data->screen_height;
     }
 
-    CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(CGDisplayCopyDisplayMode(p_data->display_id));
-    int length = CFStringGetLength(pixelEncoding);
-    length++;
-    char *psz_name = (char *)malloc(length);
-    CFStringGetCString(pixelEncoding, psz_name, length, kCFStringEncodingUTF8);
-    msg_Dbg(p_demux, "pixel encoding is '%s'", psz_name);
-    CFRelease(pixelEncoding);
-
-    if (!strcmp(psz_name, IO32BitDirectPixels)) {
-        i_chroma = VLC_CODEC_RGB32;
-        i_bits_per_pixel = 32;
-    } else if (!strcmp(psz_name, IO16BitDirectPixels)) {
-        i_chroma = VLC_CODEC_RGB16;
-        i_bits_per_pixel = 16;
-    } else if (!strcmp(psz_name, IO8BitIndexedPixels)) {
-        i_chroma = VLC_CODEC_RGB8;
-        i_bits_per_pixel = 8;
-    } else {
-        msg_Err(p_demux, "unsupported pixel encoding");
-        free(p_data);
-        return VLC_EGENERIC;
-    }
-    free(psz_name);
-
     /* setup format */
-    es_format_Init(&p_sys->fmt, VIDEO_ES, i_chroma);
+    es_format_Init(&p_sys->fmt, VIDEO_ES, VLC_CODEC_RGB32);
     p_sys->fmt.video.i_visible_width  =
     p_sys->fmt.video.i_width          = rect.size.width;
     p_sys->fmt.video.i_visible_height =
     p_sys->fmt.video.i_height         = rect.size.height;
-    p_sys->fmt.video.i_bits_per_pixel = i_bits_per_pixel;
-    p_sys->fmt.video.i_chroma         = i_chroma;
-
-    switch (i_chroma) {
-        case VLC_CODEC_RGB15:
-            p_sys->fmt.video.i_rmask = 0x7c00;
-            p_sys->fmt.video.i_gmask = 0x03e0;
-            p_sys->fmt.video.i_bmask = 0x001f;
-            break;
-        case VLC_CODEC_RGB24:
-            p_sys->fmt.video.i_rmask = 0x00ff0000;
-            p_sys->fmt.video.i_gmask = 0x0000ff00;
-            p_sys->fmt.video.i_bmask = 0x000000ff;
-            break;
-        case VLC_CODEC_RGB32:
-            p_sys->fmt.video.i_rmask = 0x00ff0000;
-            p_sys->fmt.video.i_gmask = 0x0000ff00;
-            p_sys->fmt.video.i_bmask = 0x000000ff;
-            break;
-        default:
-            msg_Warn( p_demux, "Unknown RGB masks" );
-            break;
-    }
+    p_sys->fmt.video.i_bits_per_pixel = 32;
+    p_sys->fmt.video.i_chroma         = VLC_CODEC_RGB32;
+    p_sys->fmt.video.i_rmask          = 0x00ff0000;
+    p_sys->fmt.video.i_gmask          = 0x0000ff00;
+    p_sys->fmt.video.i_bmask          = 0x000000ff;
 
     return VLC_SUCCESS;
 }
@@ -168,6 +130,12 @@ int screen_CloseCapture(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->offscreen_context)
+        CFRelease(p_data->offscreen_context);
+
+    if (p_data->offscreen_bitmap)
+        free(p_data->offscreen_bitmap);
+
     if (p_data->p_block)
         block_Release(p_data->p_block);
 
@@ -183,8 +151,6 @@ block_t *screen_Capture(demux_t *p_demux)
     block_t *p_block;
     CGRect capture_rect;
     CGImageRef image;
-    CGDataProviderRef dataProvider;
-    CFDataRef data;
 
     /* forward cursor location */
     CGPoint cursor_pos;
@@ -204,37 +170,67 @@ block_t *screen_Capture(demux_t *p_demux)
     capture_rect.size.width = p_data->width;
     capture_rect.size.height = p_data->height;
 
-#if 0
-    // FIXME: actually plot cursor image into snapshot
-    /* fetch cursor image */
-    CGImageRef cursor_image;
-    int cid = CGSMainConnectionID();
-    CGPoint outHotSpot;
-    cursor_image = CGSCreateRegisteredCursorImage(cid, (char *)"com.apple.coregraphics.GlobalCurrent", &outHotSpot);
-#endif
-
     /* fetch image data */
     image = CGDisplayCreateImageForRect(p_data->display_id, capture_rect);
-    if (image) {
-        /* build block */
-        int i_buffer = (p_sys->fmt.video.i_bits_per_pixel + 7) / 8 * p_sys->fmt.video.i_width * p_sys->fmt.video.i_height;
-        p_block = block_Alloc(i_buffer);
-        if (!p_block) {
-            msg_Warn(p_demux, "can't get block");
+    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;
         }
 
-        dataProvider = CGImageGetDataProvider(image);
-        data = CGDataProviderCopyData(dataProvider);
-        CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), p_block->p_buffer);
+        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;
+        }
 
-        CFRelease(data);
-        CFRelease(dataProvider);
-        CFRelease(image);
+        CGColorSpaceRelease(colorspace);
 
-        return p_block;
+        p_data->offscreen_rect = CGRectMake(0, 0, p_sys->fmt.video.i_width, p_sys->fmt.video.i_height);
     }
 
-    msg_Warn(p_demux, "no image!");
-    return NULL;
+    /* 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;
 }



More information about the vlc-commits mailing list