Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
1cc498b2
Commit
1cc498b2
authored
Feb 24, 2013
by
Felix Paul Kühne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
screen/mac: clean-up, improve and partially rewrite the code
TODO: cursor rendering
parent
fbf37518
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
128 additions
and
491 deletions
+128
-491
modules/access/screen/mac.c
modules/access/screen/mac.c
+128
-491
No files found.
modules/access/screen/mac.c
View file @
1cc498b2
...
...
@@ -29,49 +29,23 @@
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# i
mport
"config.h"
# i
nclude
"config.h"
#endif
#import <vlc_common.h>
#import <vlc_block.h>
// Fix ourselves ColorSync headers that gets included in ApplicationServices.
#define DisposeCMProfileIterateUPP(a) DisposeCMProfileIterateUPP(CMProfileIterateUPP userUPP __attribute__((unused)))
#define DisposeCMMIterateUPP(a) DisposeCMMIterateUPP(CMProfileIterateUPP userUPP __attribute__((unused)))
#define __MACHINEEXCEPTIONS__
#import <ApplicationServices/ApplicationServices.h>
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl.h>
#import <stdlib.h>
#import "screen.h"
typedef
int
CGSConnectionRef
;
extern
CGError
CGSNewConnection
(
void
*
,
CGSConnectionRef
*
);
extern
CGError
CGSReleaseConnection
(
CGSConnectionRef
);
extern
CGError
CGSGetGlobalCursorDataSize
(
CGSConnectionRef
,
int
*
);
extern
CGError
CGSGetGlobalCursorData
(
CGSConnectionRef
,
unsigned
char
*
,
int
*
,
int
*
,
CGRect
*
,
CGPoint
*
,
int
*
,
int
*
,
int
*
);
extern
CGError
CGSGetCurrentCursorLocation
(
CGSConnectionRef
,
CGPoint
*
);
extern
int
CGSCurrentCursorSeed
(
void
);
#import <ApplicationServices/ApplicationServices.h>
#import <QuartzCore/QuartzCore.h>
typedef
CGImageRef
(
*
typeofCGDisplayCreateImageForRect
)(
CGDirectDisplayID
displayID
,
CGRect
rect
);
#import "screen.h"
extern
int
CGSMainConnectionID
();
extern
CGImageRef
CGSCreateRegisteredCursorImage
(
int
,
char
*
,
CGPoint
*
);
struct
screen_data_t
{
CGLContextObj
screen
;
char
*
screen_image
;
CGLContextObj
clipped
;
char
*
clipped_image
;
GLuint
cursor_texture
;
int
cursor_seed
;
bool
cursor_need_update
;
CGRect
cursor_rect
;
CGPoint
cursor_hot
;
double
cursor_texture_map_u
,
cursor_texture_map_v
;
block_t
*
p_block
;
int
width
;
int
height
;
...
...
@@ -81,88 +55,45 @@ struct screen_data_t
int
screen_width
;
int
screen_height
;
CGSConnectionRef
connection
;
CFBundleRef
bundle
;
typeofCGDisplayCreateImageForRect
myCGDisplayCreateImageForRect
;
CGDirectDisplayID
display_id
;
};
CGLError
screen_CreateContext
(
CGLContextObj
*
context
,
CGLPixelFormatAttribute
a0
,
CGLPixelFormatAttribute
a1
,
CGLPixelFormatAttribute
a2
,
CGLPixelFormatAttribute
a3
);
int
screen_DrawCursor
(
demux_sys_t
*
p_sys
,
CGPoint
*
cursor_pos
);
int
screen_CaptureScreen
(
demux_sys_t
*
p_sys
);
int
screen_InitCapture
(
demux_t
*
p_demux
)
int
screen_InitCapture
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
screen_data_t
*
p_data
;
CGLError
returnedError
;
unsigned
int
i
;
int
i_bits_per_pixel
,
i_chroma
=
0
;
p_sys
->
p_data
=
p_data
=
(
screen_data_t
*
)
calloc
(
1
,
sizeof
(
screen_data_t
)
);
p_sys
->
p_data
=
p_data
=
calloc
(
1
,
sizeof
(
screen_data_t
)
);
if
(
!
p_data
)
return
VLC_ENOMEM
;
/* fetch the screen we should capture */
p_data
->
display_id
=
kCGDirectMainDisplay
;
unsigned
int
displayCount
;
displayCount
=
0
;
returnedError
=
CGGetOnlineDisplayList
(
0
,
NULL
,
&
displayCount
);
if
(
!
returnedError
)
{
unsigned
int
displayCount
=
0
;
returnedError
=
CGGetOnlineDisplayList
(
0
,
NULL
,
&
displayCount
);
if
(
!
returnedError
)
{
CGDirectDisplayID
*
ids
;
ids
=
(
CGDirectDisplayID
*
)
malloc
(
displayCount
*
sizeof
(
CGDirectDisplayID
)
);
returnedError
=
CGGetOnlineDisplayList
(
displayCount
,
ids
,
&
displayCount
);
if
(
!
returnedError
)
{
if
(
p_sys
->
i_display_id
>
0
)
{
for
(
i
=
0
;
i
<
displayCount
;
i
++
)
{
if
(
p_sys
->
i_display_id
==
ids
[
i
]
)
{
if
(
!
returnedError
)
{
if
(
p_sys
->
i_display_id
>
0
)
{
for
(
unsigned
int
i
=
0
;
i
<
displayCount
;
i
++
)
{
if
(
p_sys
->
i_display_id
==
ids
[
i
])
{
p_data
->
display_id
=
ids
[
i
];
break
;
}
}
}
else
if
(
p_sys
->
i_screen_index
>
0
&&
p_sys
->
i_screen_index
<=
displayCount
)
{
}
else
if
(
p_sys
->
i_screen_index
>
0
&&
p_sys
->
i_screen_index
<=
displayCount
)
p_data
->
display_id
=
ids
[
p_sys
->
i_screen_index
-
1
];
}
}
free
(
ids
);
}
/* CGImage Function
* CGDisplayCreateImageForRect is available in Mac OS X v10.6 and later */
p_data
->
myCGDisplayCreateImageForRect
=
NULL
;
CFURLRef
frameworkURL
=
NULL
;
CFStringRef
path
=
CFSTR
(
"file://localhost/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework"
);
frameworkURL
=
CFURLCreateWithString
(
kCFAllocatorDefault
,
path
,
NULL
);
if
(
frameworkURL
!=
NULL
)
{
p_data
->
bundle
=
CFBundleCreate
(
kCFAllocatorDefault
,
frameworkURL
);
if
(
p_data
->
bundle
!=
NULL
)
{
p_data
->
myCGDisplayCreateImageForRect
=
(
typeofCGDisplayCreateImageForRect
)
CFBundleGetFunctionPointerForName
(
p_data
->
bundle
,
CFSTR
(
"CGDisplayCreateImageForRect"
)
);
free
(
ids
);
}
CFRelease
(
frameworkURL
);
}
/* Screen Size */
CGRect
rect
=
CGDisplayBounds
(
p_data
->
display_id
);
/* Get the device context for the whole screen */
CGRect
rect
=
CGDisplayBounds
(
p_data
->
display_id
);
p_data
->
screen_left
=
rect
.
origin
.
x
;
p_data
->
screen_top
=
rect
.
origin
.
y
;
p_data
->
screen_width
=
rect
.
size
.
width
;
...
...
@@ -170,437 +101,143 @@ int screen_InitCapture( demux_t *p_demux )
p_data
->
width
=
p_sys
->
i_width
;
p_data
->
height
=
p_sys
->
i_height
;
if
(
p_data
->
width
<=
0
||
p_data
->
height
<=
0
)
{
if
(
p_data
->
width
<=
0
||
p_data
->
height
<=
0
)
{
p_data
->
width
=
p_data
->
screen_width
;
p_data
->
height
=
p_data
->
screen_height
;
}
/* Screen Context */
if
(
p_data
->
myCGDisplayCreateImageForRect
==
NULL
)
{
returnedError
=
screen_CreateContext
(
&
p_data
->
screen
,
kCGLPFAFullScreen
,
kCGLPFADisplayMask
,
(
CGLPixelFormatAttribute
)
CGDisplayIDToOpenGLDisplayMask
(
p_data
->
display_id
),
(
CGLPixelFormatAttribute
)
0
);
if
(
returnedError
)
goto
errorHandling
;
returnedError
=
CGLSetCurrentContext
(
p_data
->
screen
);
if
(
returnedError
)
goto
errorHandling
;
returnedError
=
CGLSetFullScreen
(
p_data
->
screen
);
if
(
returnedError
)
goto
errorHandling
;
}
/* Clipped Context */
returnedError
=
screen_CreateContext
(
&
p_data
->
clipped
,
kCGLPFAOffScreen
,
kCGLPFAColorSize
,
(
CGLPixelFormatAttribute
)
32
,
(
CGLPixelFormatAttribute
)
0
);
if
(
returnedError
)
goto
errorHandling
;
returnedError
=
CGLSetCurrentContext
(
p_data
->
clipped
);
if
(
returnedError
)
goto
errorHandling
;
/* Clipped Image */
p_data
->
clipped_image
=
(
char
*
)
malloc
(
p_data
->
width
*
p_data
->
height
*
4
);
returnedError
=
CGLSetOffScreen
(
p_data
->
clipped
,
p_data
->
width
,
p_data
->
height
,
p_data
->
width
*
4
,
p_data
->
clipped_image
);
if
(
returnedError
)
goto
errorHandling
;
/* Screen Image */
if
(
p_data
->
myCGDisplayCreateImageForRect
!=
NULL
)
{
p_data
->
screen_image
=
(
char
*
)
malloc
(
p_data
->
screen_width
*
p_data
->
screen_height
*
4
);
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
;
}
else
{
p_data
->
screen_image
=
(
char
*
)
malloc
(
p_data
->
width
*
p_data
->
height
*
4
);
free
(
psz_name
);
/* setup format */
es_format_Init
(
&
p_sys
->
fmt
,
VIDEO_ES
,
i_chroma
);
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
;
}
/* Cursor */
CGSNewConnection
(
NULL
,
&
(
p_data
->
connection
)
);
p_data
->
cursor_need_update
=
1
;
p_data
->
cursor_seed
=
0
;
glGenTextures
(
1
,
&
(
p_data
->
cursor_texture
)
);
glBindTexture
(
GL_TEXTURE_2D
,
p_data
->
cursor_texture
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MAG_FILTER
,
GL_NEAREST
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MIN_FILTER
,
GL_NEAREST
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_S
,
GL_CLAMP
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_T
,
GL_CLAMP
);
/* System */
es_format_Init
(
&
p_sys
->
fmt
,
VIDEO_ES
,
VLC_CODEC_RGB32
);
/* p_sys->fmt.video.i_* must set to screen size, not subscreen size */
p_sys
->
fmt
.
video
.
i_width
=
p_data
->
screen_width
;
p_sys
->
fmt
.
video
.
i_visible_width
=
p_data
->
screen_width
;
p_sys
->
fmt
.
video
.
i_height
=
p_data
->
screen_height
;
p_sys
->
fmt
.
video
.
i_bits_per_pixel
=
32
;
return
VLC_SUCCESS
;
errorHandling:
msg_Err
(
p_demux
,
"Core OpenGL failure: %s"
,
CGLErrorString
(
returnedError
)
);
return
VLC_EGENERIC
;
}
int
screen_CloseCapture
(
demux_t
*
p_demux
)
int
screen_CloseCapture
(
demux_t
*
p_demux
)
{
screen_data_t
*
p_data
=
(
screen_data_t
*
)
p_demux
->
p_sys
->
p_data
;
CGLSetCurrentContext
(
NULL
);
/* Cursor */
glBindTexture
(
GL_TEXTURE_2D
,
0
);
glDeleteTextures
(
1
,
&
(
p_data
->
cursor_texture
)
);
CGSReleaseConnection
(
p_data
->
connection
);
/* Screen Image */
if
(
p_data
->
screen_image
!=
NULL
)
{
free
(
p_data
->
screen_image
);
p_data
->
screen_image
=
NULL
;
}
/* Clipped Image */
if
(
p_data
->
clipped_image
!=
NULL
)
{
free
(
p_data
->
clipped_image
);
p_data
->
clipped_image
=
NULL
;
}
/* Clipped Context */
CGLClearDrawable
(
p_data
->
clipped
);
CGLDestroyContext
(
p_data
->
clipped
);
/* Screen Context */
if
(
p_data
->
myCGDisplayCreateImageForRect
==
NULL
)
{
CGLClearDrawable
(
p_data
->
screen
);
CGLDestroyContext
(
p_data
->
screen
);
}
/* CGImage */
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
screen_data_t
*
p_data
=
p_sys
->
p_data
;
CFRelease
(
p_data
->
bundle
);
if
(
p_data
->
p_block
)
block_Release
(
p_data
->
p_block
);
free
(
p_data
);
free
(
p_data
);
return
VLC_SUCCESS
;
}
block_t
*
screen_Capture
(
demux_t
*
p_demux
)
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
;
}
CGRect
capture_rect
;
CGImageRef
image
;
CGDataProviderRef
dataProvider
;
CFDataRef
data
;
/* forward cursor location */
CGPoint
cursor_pos
;
CGError
cursor_result
;
cursor_pos
.
x
=
0
;
cursor_pos
.
y
=
0
;
cursor_result
=
CGSGetCurrentCursorLocation
(
p_data
->
connection
,
&
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
&&
cursor_result
==
kCGErrorSuccess
)
{
FollowMouse
(
p_sys
,
cursor_pos
.
x
,
cursor_pos
.
y
);
}
screen_CaptureScreen
(
p_sys
);
CGLSetCurrentContext
(
p_data
->
clipped
);
glClearColor
(
0
.
0
f
,
0
.
0
f
,
0
.
0
f
,
1
.
0
f
);
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
;
}
CGLError
screen_CreateContext
(
CGLContextObj
*
context
,
CGLPixelFormatAttribute
a0
,
CGLPixelFormatAttribute
a1
,
CGLPixelFormatAttribute
a2
,
CGLPixelFormatAttribute
a3
)
{
CGLPixelFormatAttribute
attribs
[
4
];
CGLPixelFormatObj
pix
;
GLint
npix
;
CGLError
returnedError
;
attribs
[
0
]
=
a0
;
attribs
[
1
]
=
a1
;
attribs
[
2
]
=
a2
;
attribs
[
3
]
=
a3
;
returnedError
=
CGLChoosePixelFormat
(
attribs
,
&
pix
,
&
npix
);
if
(
returnedError
)
{
return
returnedError
;
}
returnedError
=
CGLCreateContext
(
pix
,
NULL
,
context
);
if
(
returnedError
)
{
return
returnedError
;
}
if
(
p_sys
->
b_follow_mouse
)
FollowMouse
(
p_sys
,
cursor_pos
.
x
,
cursor_pos
.
y
);
returnedError
=
CGLDestroyPixelFormat
(
pix
);
if
(
returnedError
)
{
return
returnedError
;
}
return
kCGLNoError
;
}
#define POT(V,N) V = 1; while( V < N ) { V <<= 1; }
int
screen_DrawCursor
(
demux_sys_t
*
p_sys
,
CGPoint
*
cursor_pos
)
{
int
size
;
int
tmp1
,
tmp2
,
tmp3
,
tmp4
;
unsigned
char
*
cursor_image
;
screen_data_t
*
p_data
=
p_sys
->
p_data
;
int
seed
=
CGSCurrentCursorSeed
();
if
(
seed
!=
p_data
->
cursor_seed
)
{
p_data
->
cursor_need_update
=
1
;
if
(
CGSGetGlobalCursorDataSize
(
p_data
->
connection
,
&
size
)
!=
kCGErrorSuccess
)
{
return
VLC_EGENERIC
;
}
cursor_image
=
(
unsigned
char
*
)
malloc
(
size
);
if
(
CGSGetGlobalCursorData
(
p_data
->
connection
,
cursor_image
,
&
size
,
&
tmp1
,
&
p_data
->
cursor_rect
,
&
p_data
->
cursor_hot
,
&
tmp2
,
&
tmp3
,
&
tmp4
)
!=
kCGErrorSuccess
)
{
free
(
cursor_image
);
return
VLC_EGENERIC
;
}
long
int
pot_width
,
pot_height
;
POT
(
pot_width
,
p_data
->
cursor_rect
.
size
.
width
);
POT
(
pot_height
,
p_data
->
cursor_rect
.
size
.
height
);
p_data
->
cursor_texture_map_u
=
p_data
->
cursor_rect
.
size
.
width
/
(
double
)
pot_width
;
p_data
->
cursor_texture_map_v
=
p_data
->
cursor_rect
.
size
.
height
/
(
double
)
pot_height
;
/* We need transparent image larger than original,
* use calloc to clear alpha value to 0. */
char
*
pot_cursor_image
=
(
char
*
)
calloc
(
pot_width
*
pot_height
*
4
,
sizeof
(
char
)
);
int
width
,
height
;
char
*
from
,
*
to
;
width
=
p_data
->
cursor_rect
.
size
.
width
;
height
=
p_data
->
cursor_rect
.
size
.
height
;
from
=
(
char
*
)
cursor_image
;
to
=
pot_cursor_image
;
#ifdef __LITTLE_ENDIAN__
int
y
,
fromwidth
,
towidth
;
fromwidth
=
width
*
4
;
towidth
=
pot_width
*
4
;
for
(
y
=
height
;
y
;
y
--
)
{
memcpy
(
to
,
from
,
fromwidth
);
to
+=
towidth
;
from
+=
fromwidth
;
}
#else
int
x
,
y
,
diff
;
diff
=
(
pot_width
-
width
)
*
4
;
for
(
y
=
height
;
y
;
y
--
)
{
for
(
x
=
width
;
x
;
x
--
)
{
to
[
0
]
=
from
[
3
];
to
[
1
]
=
from
[
2
];
to
[
2
]
=
from
[
1
];
to
[
3
]
=
from
[
0
];
to
+=
4
;
from
+=
4
;
}
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
;
to
+=
diff
;
}
#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
glEnable
(
GL_TEXTURE_2D
);
glBindTexture
(
GL_TEXTURE_2D
,
p_data
->
cursor_texture
);
glTexImage2D
(
GL_TEXTURE_2D
,
0
,
GL_RGBA8
,
pot_width
,
pot_height
,
0
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
pot_cursor_image
);
p_data
->
cursor_need_update
=
0
;
p_data
->
cursor_seed
=
seed
;
free
(
pot_cursor_image
);
free
(
cursor_image
);
}
else
if
(
p_data
->
cursor_need_update
)
{
return
VLC_EGENERIC
;
/* 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"
);
return
NULL
;
}
double
x
,
y
;
double
x1
,
y1
,
x2
,
y2
;
x
=
cursor_pos
->
x
-
p_sys
->
i_left
-
p_data
->
cursor_hot
.
x
;
y
=
cursor_pos
->
y
-
p_sys
->
i_top
-
p_data
->
cursor_hot
.
y
;
x1
=
2
.
0
*
x
/
p_data
->
width
-
1
.
0
;
y1
=
2
.
0
*
y
/
p_data
->
height
-
1
.
0
;
x2
=
2
.
0
*
(
x
+
p_data
->
cursor_rect
.
size
.
width
)
/
p_data
->
width
-
1
.
0
;
y2
=
2
.
0
*
(
y
+
p_data
->
cursor_rect
.
size
.
height
)
/
p_data
->
height
-
1
.
0
;
glColor3f
(
1
.
0
f
,
1
.
0
f
,
1
.
0
f
);
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
(
x1
,
y1
);
glTexCoord2f
(
p_data
->
cursor_texture_map_u
,
0
.
0
);
glVertex2f
(
x2
,
y1
);
glTexCoord2f
(
p_data
->
cursor_texture_map_u
,
p_data
->
cursor_texture_map_v
);
glVertex2f
(
x2
,
y2
);
glTexCoord2f
(
0
.
0
,
p_data
->
cursor_texture_map_v
);
glVertex2f
(
x1
,
y2
);
glEnd
();
glDisable
(
GL_BLEND
);
glDisable
(
GL_TEXTURE_2D
);
dataProvider
=
CGImageGetDataProvider
(
image
);
data
=
CGDataProviderCopyData
(
dataProvider
);
CFDataGetBytes
(
data
,
CFRangeMake
(
0
,
CFDataGetLength
(
data
)),
p_block
->
p_buffer
);
return
VLC_SUCCESS
;
}
CFRelease
(
data
);
CFRelease
(
dataProvider
);
CFRelease
(
image
);
int
screen_CaptureScreen
(
demux_sys_t
*
p_sys
)
{
screen_data_t
*
p_data
=
p_sys
->
p_data
;
if
(
p_data
->
myCGDisplayCreateImageForRect
!=
NULL
)
{
CGImageRef
captured_image
;
CGContextRef
captured_bitmap
;
CGRect
capture_rect
;
CGRect
draw_rect
;
free
(
p_sys
->
p_mouse
);
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
;
captured_image
=
p_data
->
myCGDisplayCreateImageForRect
(
p_data
->
display_id
,
capture_rect
);
captured_bitmap
=
CGBitmapContextCreate
(
(
unsigned
char
*
)
p_data
->
screen_image
,
capture_rect
.
size
.
width
,
capture_rect
.
size
.
height
,
8
,
capture_rect
.
size
.
width
*
4
,
CGColorSpaceCreateDeviceRGB
(),
kCGImageAlphaPremultipliedLast
);
draw_rect
.
size
.
width
=
CGImageGetWidth
(
captured_image
);
draw_rect
.
size
.
height
=
CGImageGetHeight
(
captured_image
);
draw_rect
.
origin
.
x
=
0
;
draw_rect
.
origin
.
y
=
capture_rect
.
size
.
height
-
draw_rect
.
size
.
height
;
CGContextDrawImage
(
captured_bitmap
,
draw_rect
,
captured_image
);
CGContextRelease
(
captured_bitmap
);
CGImageRelease
(
captured_image
);
}
else
{
CGLSetCurrentContext
(
p_data
->
screen
);
glReadPixels
(
p_sys
->
i_left
,
p_data
->
screen_height
-
p_sys
->
i_top
-
p_data
->
height
,
p_data
->
width
,
p_data
->
height
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
p_data
->
screen_image
);
return
p_block
;
}
return
VLC_SUCCESS
;
msg_Warn
(
p_demux
,
"no image!"
);
return
NULL
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment