Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
Commits
70bc0a33
Commit
70bc0a33
authored
Apr 21, 2013
by
Felix Paul Kühne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New CoreGraphics based video output drawing on CoreAnimation layers
parent
a01f4017
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
397 additions
and
0 deletions
+397
-0
configure.ac
configure.ac
+9
-0
modules/video_output/Modules.am
modules/video_output/Modules.am
+1
-0
modules/video_output/coregraphicslayer.m
modules/video_output/coregraphicslayer.m
+387
-0
No files found.
configure.ac
View file @
70bc0a33
...
...
@@ -3119,6 +3119,15 @@ then
VLC_ADD_PLUGIN([vout_macosx])
fi
dnl
dnl Mac CoreGraphics Layer Vout
AC_ARG_ENABLE(coregraphicslayer-vout,
[ --enable-coregraphicslayer-vout CoreGraphics layered video output module (default disabled)])
if test "${enable_coregraphicslayer_vout}" = "yes"; then
VLC_ADD_LIBS([vout_coregraphicslayer],[-Wl,-framework,Cocoa])
VLC_ADD_LIBS([vout_coregraphicslayer],[-Wl,-framework,QuartzCore])
VLC_ADD_PLUGIN([vout_coregraphicslayer])
fi
dnl
dnl freetype module
...
...
modules/video_output/Modules.am
View file @
70bc0a33
...
...
@@ -7,6 +7,7 @@ SOURCES_directfb = directfb.c
SOURCES_vmem = vmem.c
SOURCES_yuv = yuv.c
SOURCES_vout_macosx = macosx.m opengl.h opengl.c
SOURCES_vout_coregraphicslayer = coregraphicslayer.m
SOURCES_vout_ios2 = ios2.m opengl.h opengl.c
SOURCES_android_surface = androidsurface.c
...
...
modules/video_output/coregraphicslayer.m
0 → 100644
View file @
70bc0a33
/*****************************************************************************
* coregraphicslayer.m: CoreGraphics video output for NPAPI plugins
*****************************************************************************
* Copyright (C) 2013 VLC authors and VideoLAN
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne # videolan.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# import "config.h"
#endif
#import <vlc_common.h>
#import <vlc_plugin.h>
#import <vlc_vout_display.h>
#import <vlc_picture_pool.h>
#import <QuartzCore/QuartzCore.h>
#import <AppKit/AppKit.h>
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
()
set_description
(
N_
(
"CoreGraphics video output"
))
set_shortname
(
"CoreGraphics"
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_capability
(
"vout display"
,
0
)
set_callbacks
(
Open
,
Close
)
vlc_module_end
()
@protocol
VLCCoreGraphicsVideoLayerEmbedding
<
NSObject
>
-
(
void
)
addVoutLayer
:(
CALayer
*
)
aLayer
;
-
(
void
)
removeVoutLayer
:(
CALayer
*
)
aLayer
;
-
(
CGSize
)
currentOutputSize
;
@end
@interface
VLCCoreGraphicsLayer
:
CALayer
{
CGImageRef
_lastFrame
;
bool
lock
;
vout_display_t
*
_vd
;
}
@property
(
nonatomic
)
vout_display_t
*
vd
;
-
(
void
)
setLastFrame
:(
CGImageRef
)
lastFrame
;
@end
/*****************************************************************************
* Local prototypes
*****************************************************************************/
struct
vout_display_sys_t
{
picture_pool_t
*
pool
;
picture_resource_t
resource
;
VLCCoreGraphicsLayer
*
cgLayer
;
vout_window_t
*
embed
;
bool
has_first_frame
;
size_t
componentsPerPixel
;
size_t
bitsPerComponent
;
size_t
bitsPerPixel
;
CALayer
<
VLCCoreGraphicsVideoLayerEmbedding
>
*
container
;
CGColorSpaceRef
colorspace
;
};
static
picture_pool_t
*
Pool
(
vout_display_t
*
,
unsigned
);
static
void
Display
(
vout_display_t
*
,
picture_t
*
,
subpicture_t
*
);
static
int
Control
(
vout_display_t
*
,
int
,
va_list
);
/*****************************************************************************
* OpenVideo: activates dummy vout display method
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
object
)
{
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
vout_display_sys_t
*
sys
=
calloc
(
1
,
sizeof
(
*
sys
));
NSAutoreleasePool
*
nsPool
=
nil
;
if
(
!
sys
)
return
VLC_ENOMEM
;
sys
->
pool
=
NULL
;
id
container
=
var_CreateGetAddress
(
vd
,
"drawable-nsobject"
);
if
(
container
)
vout_display_DeleteWindow
(
vd
,
NULL
);
else
{
vout_window_cfg_t
wnd_cfg
;
memset
(
&
wnd_cfg
,
0
,
sizeof
(
wnd_cfg
));
wnd_cfg
.
type
=
VOUT_WINDOW_TYPE_NSOBJECT
;
wnd_cfg
.
x
=
var_InheritInteger
(
vd
,
"video-x"
);
wnd_cfg
.
y
=
var_InheritInteger
(
vd
,
"video-y"
);
wnd_cfg
.
height
=
vd
->
cfg
->
display
.
height
;
wnd_cfg
.
width
=
vd
->
cfg
->
display
.
width
;
sys
->
embed
=
vout_display_NewWindow
(
vd
,
&
wnd_cfg
);
if
(
sys
->
embed
)
container
=
sys
->
embed
->
handle
.
nsobject
;
if
(
!
container
)
{
msg_Err
(
vd
,
"No drawable-nsobject found!"
);
goto
bailout
;
}
}
/* store for later, released in Close() */
sys
->
container
=
[
container
retain
];
/* allocate pool */
nsPool
=
[[
NSAutoreleasePool
alloc
]
init
];
if
([
container
respondsToSelector
:
@selector
(
addVoutLayer
:)])
{
msg_Dbg
(
vd
,
"container implements implicit protocol"
);
sys
->
cgLayer
=
[[
VLCCoreGraphicsLayer
alloc
]
init
];
[
container
addVoutLayer
:
sys
->
cgLayer
];
}
else
if
([
container
respondsToSelector
:
@selector
(
addSublayer
:)]
||
[
container
isKindOfClass
:[
CALayer
class
]])
{
msg_Dbg
(
vd
,
"container doesn't implement implicit protocol, fallback mode used"
);
sys
->
cgLayer
=
[[
VLCCoreGraphicsLayer
alloc
]
init
];
[
container
addSublayer
:
sys
->
cgLayer
];
}
else
{
msg_Err
(
vd
,
"Provided NSObject container isn't compatible"
);
goto
bailout
;
}
[
sys
->
cgLayer
setVd
:
vd
];
/* setup output format */
video_format_t
fmt
=
vd
->
fmt
;
char
*
chroma
=
"RGBA"
;
fmt
.
i_chroma
=
vlc_fourcc_GetCodecFromString
(
VIDEO_ES
,
chroma
);
msg_Dbg
(
vd
,
"forcing chroma 0x%.8x (%4.4s)"
,
fmt
.
i_chroma
,
(
char
*
)
&
fmt
.
i_chroma
);
video_format_FixRgb
(
&
fmt
);
msg_Dbg
(
vd
,
"will use pixel format %4.4s"
,
(
char
*
)
&
fmt
.
i_chroma
);
/* setup vout display */
vout_display_info_t
info
=
vd
->
info
;
info
.
has_hide_mouse
=
false
;
vd
->
sys
=
sys
;
vd
->
fmt
=
fmt
;
vd
->
info
=
info
;
vd
->
pool
=
Pool
;
vd
->
display
=
Display
;
vd
->
control
=
Control
;
vd
->
prepare
=
NULL
;
vd
->
manage
=
NULL
;
/* setup initial state */
CGSize
outputSize
;
if
([
container
respondsToSelector
:
@selector
(
currentOutputSize
)])
outputSize
=
[
container
currentOutputSize
];
else
outputSize
=
[
sys
->
container
visibleRect
].
size
;
vout_display_SendEventFullscreen
(
vd
,
false
);
vout_display_SendEventDisplaySize
(
vd
,
(
int
)
outputSize
.
width
,
(
int
)
outputSize
.
height
,
false
);
sys
->
colorspace
=
CGColorSpaceCreateDeviceRGB
();
sys
->
componentsPerPixel
=
4
;
sys
->
bitsPerComponent
=
sizeof
(
unsigned
char
)
*
8
;
sys
->
bitsPerPixel
=
sys
->
bitsPerComponent
*
sys
->
componentsPerPixel
;
return
VLC_SUCCESS
;
bailout:
if
(
nsPool
)
[
nsPool
release
];
return
VLC_EGENERIC
;
}
static
void
Close
(
vlc_object_t
*
object
)
{
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
sys
->
pool
)
picture_pool_Delete
(
sys
->
pool
);
if
(
sys
->
cgLayer
)
{
if
([
sys
->
container
respondsToSelector
:
@selector
(
removeVoutLayer
:)])
[
sys
->
container
removeVoutLayer
:
sys
->
cgLayer
];
else
[
sys
->
cgLayer
removeFromSuperlayer
];
[
sys
->
cgLayer
release
];
}
if
(
sys
->
container
)
[
sys
->
container
release
];
free
(
sys
);
}
static
picture_pool_t
*
Pool
(
vout_display_t
*
vd
,
unsigned
count
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
!
sys
->
pool
)
sys
->
pool
=
picture_pool_NewFromFormat
(
&
vd
->
fmt
,
count
);
return
sys
->
pool
;
}
static
void
Display
(
vout_display_t
*
vd
,
picture_t
*
picture
,
subpicture_t
*
subpicture
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
!
sys
->
cgLayer
)
{
msg_Warn
(
vd
,
"no cglayer to Display in"
);
return
;
}
uint32_t
sourceWidth
,
sourceHeight
;
sourceWidth
=
picture
->
p
[
0
].
i_visible_pitch
/
picture
->
p
[
0
].
i_pixel_pitch
;
sourceHeight
=
picture
->
p
[
0
].
i_visible_lines
;
const
int
crop_offset
=
vd
->
source
.
i_y_offset
*
picture
->
p
->
i_pitch
+
vd
->
source
.
i_x_offset
*
picture
->
p
->
i_pixel_pitch
;
CFDataRef
dataRef
=
CFDataCreateWithBytesNoCopy
(
kCFAllocatorDefault
,
&
picture
->
p
->
p_pixels
[
crop_offset
],
sizeof
(
picture
->
p
->
p_pixels
[
crop_offset
]),
kCFAllocatorNull
);
CGDataProviderRef
dataProvider
=
CGDataProviderCreateWithCFData
(
dataRef
);
CGImageRef
newFrame
=
CGImageCreate
(
sourceWidth
,
sourceHeight
,
sys
->
bitsPerComponent
,
sys
->
bitsPerPixel
,
sys
->
componentsPerPixel
*
sourceWidth
,
sys
->
colorspace
,
kCGBitmapByteOrder16Big
,
dataProvider
,
NULL
,
true
,
kCGRenderingIntentPerceptual
);
CGDataProviderRelease
(
dataProvider
);
if
(
!
newFrame
)
goto
end
;
[
sys
->
cgLayer
setLastFrame
:
newFrame
];
end:
VLC_UNUSED
(
subpicture
);
picture_Release
(
picture
);
}
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
args
)
{
VLC_UNUSED
(
vd
);
VLC_UNUSED
(
query
);
VLC_UNUSED
(
args
);
return
VLC_SUCCESS
;
}
@implementation
VLCCoreGraphicsLayer
@synthesize
vd
=
_vd
;
-
(
id
)
init
{
if
(
self
=
[
super
init
])
{
[
CATransaction
begin
];
self
.
needsDisplayOnBoundsChange
=
YES
;
self
.
autoresizingMask
=
kCALayerWidthSizable
|
kCALayerHeightSizable
;
[
CATransaction
commit
];
}
return
self
;
}
-
(
bool
)
locked
{
return
lock
;
}
-
(
void
)
setLastFrame
:(
CGImageRef
)
lastFrame
{
if
(
lock
)
{
/* drop frame since we currently drawing */
CGImageRelease
(
lastFrame
);
return
;
}
_lastFrame
=
CGImageCreateCopy
(
lastFrame
);
CGImageRelease
(
lastFrame
);
CGRect
invalidRect
=
CGRectMake
(
0
,
0
,
CGImageGetWidth
(
_lastFrame
),
CGImageGetHeight
(
_lastFrame
));
[
CATransaction
begin
];
[
self
setNeedsDisplayInRect
:
invalidRect
];
[
CATransaction
commit
];
}
-
(
void
)
drawInContext
:(
CGContextRef
)
cgContext
{
if
(
!
cgContext
)
return
;
if
(
!
_lastFrame
)
return
;
if
(
lock
)
return
;
lock
=
YES
;
CGRect
layerRect
=
self
.
bounds
;
float
display_width
=
0
.;
float
display_height
=
0
.;
float
media_width
=
CGImageGetWidth
(
_lastFrame
);
float
media_height
=
CGImageGetHeight
(
_lastFrame
);
float
src_aspect
=
(
float
)
media_width
/
media_height
;
float
dst_aspect
=
(
float
)
layerRect
.
size
.
width
/
layerRect
.
size
.
height
;
if
(
src_aspect
>
dst_aspect
)
{
if
(
layerRect
.
size
.
width
!=
media_width
)
{
//don't scale if size equal
display_width
=
layerRect
.
size
.
width
;
display_height
=
display_width
/
src_aspect
;
// + 0.5);
}
else
{
display_width
=
media_width
;
display_height
=
media_height
;
}
}
else
{
if
(
layerRect
.
size
.
height
!=
media_height
)
{
//don't scale if size equal
display_height
=
layerRect
.
size
.
height
;
display_width
=
display_height
*
src_aspect
;
// + 0.5);
}
else
{
display_width
=
media_width
;
display_height
=
media_height
;
}
}
/* Compute the position of the video */
float
left
=
(
layerRect
.
size
.
width
-
display_width
)
/
2
.;
float
top
=
(
layerRect
.
size
.
height
-
display_height
)
/
2
.;
CGContextSaveGState
(
cgContext
);
// draw a clear background
CGContextClearRect
(
cgContext
,
CGRectMake
(
0
.,
0
.,
layerRect
.
size
.
width
,
layerRect
.
size
.
height
));
// draw the image
CGRect
rect
=
CGRectMake
(
left
,
top
,
display_width
,
display_height
);
CGContextDrawImage
(
cgContext
,
rect
,
_lastFrame
);
lock
=
NO
;
CGContextRestoreGState
(
cgContext
);
}
-
(
void
)
resizeWithOldSuperlayerSize
:(
CGSize
)
size
{
[
super
resizeWithOldSuperlayerSize
:
size
];
if
(
!
_vd
)
return
;
CGSize
outputSize
=
[
_vd
->
sys
->
container
currentOutputSize
];
vout_display_place_t
place
;
vout_display_cfg_t
cfg_tmp
=
*
(
_vd
->
cfg
);
cfg_tmp
.
display
.
width
=
outputSize
.
width
;
cfg_tmp
.
display
.
height
=
outputSize
.
height
;
vout_display_PlacePicture
(
&
place
,
&
_vd
->
source
,
&
cfg_tmp
,
false
);
vout_display_SendEventDisplaySize
(
_vd
,
outputSize
.
width
,
outputSize
.
height
,
_vd
->
cfg
->
is_fullscreen
);
}
@end
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