mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
osxvideosink: implement the xoverlay interface. Fixes #618349.
This commit is contained in:
parent
bcde9fab09
commit
5f9f71b38e
4 changed files with 155 additions and 15 deletions
|
@ -56,6 +56,10 @@ struct _GstOSXImage;
|
|||
- (void) setFullScreen: (BOOL) flag;
|
||||
- (void) reshape;
|
||||
- (void) setVideoSize: (int) w: (int) h;
|
||||
- (BOOL) haveSuperview;
|
||||
- (void) haveSuperviewReal: (NSMutableArray *)closure;
|
||||
- (void) addToSuperview: (NSView *)superview;
|
||||
- (void) removeFromSuperview: (id)unused;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -383,6 +383,37 @@
|
|||
[self initTextures];
|
||||
}
|
||||
|
||||
- (void) haveSuperviewReal:(NSMutableArray *)closure {
|
||||
BOOL haveSuperview = [self superview] != nil;
|
||||
[closure addObject:[NSNumber numberWithBool:haveSuperview]];
|
||||
}
|
||||
|
||||
- (BOOL) haveSuperview {
|
||||
NSMutableArray *closure = [NSMutableArray arrayWithCapacity:1];
|
||||
[self performSelectorOnMainThread:@selector(haveSuperviewReal:)
|
||||
withObject:(id)closure waitUntilDone:YES];
|
||||
|
||||
return [[closure objectAtIndex:0] boolValue];
|
||||
}
|
||||
|
||||
- (void) addToSuperviewReal:(NSView *)superview {
|
||||
NSRect bounds;
|
||||
[superview addSubview:self];
|
||||
bounds = [superview bounds];
|
||||
[self setFrame:bounds];
|
||||
[self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
|
||||
}
|
||||
|
||||
- (void) addToSuperview: (NSView *)superview {
|
||||
[self performSelectorOnMainThread:@selector(addToSuperviewReal:)
|
||||
withObject:superview waitUntilDone:YES];
|
||||
}
|
||||
|
||||
- (void) removeFromSuperview: (id)unused
|
||||
{
|
||||
[self removeFromSuperview];
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
GST_LOG ("dealloc called");
|
||||
if (data) g_free(data);
|
||||
|
|
|
@ -70,6 +70,7 @@ struct _GstOSXVideoSink {
|
|||
/* Our element stuff */
|
||||
GstVideoSink videosink;
|
||||
GstOSXWindow *osxwindow;
|
||||
NSView *superview;
|
||||
};
|
||||
|
||||
struct _GstOSXVideoSinkClass {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <gst/interfaces/xoverlay.h>
|
||||
|
||||
#include "osxvideosink.h"
|
||||
#include <unistd.h>
|
||||
|
@ -52,7 +53,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
GST_STATIC_CAPS ("video/x-raw-yuv, "
|
||||
"framerate = (fraction) [ 0, MAX ], "
|
||||
"width = (int) [ 1, MAX ], "
|
||||
"height = (int) [ 1, MAX ], "
|
||||
"height = (int) [ 1, MAX ], "
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
"format = (fourcc) YUY2")
|
||||
#else
|
||||
|
@ -63,27 +64,30 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_EMBED
|
||||
ARG_EMBED,
|
||||
};
|
||||
|
||||
static void gst_osx_video_sink_osxwindow_destroy (GstOSXVideoSink * osxvideosink);
|
||||
|
||||
static GstVideoSinkClass *parent_class = NULL;
|
||||
|
||||
/* This function handles osx window creation */
|
||||
static GstOSXWindow *
|
||||
gst_osx_video_sink_osxwindow_new (GstOSXVideoSink * osxvideosink, gint width,
|
||||
static gboolean
|
||||
gst_osx_video_sink_osxwindow_create (GstOSXVideoSink * osxvideosink, gint width,
|
||||
gint height)
|
||||
{
|
||||
NSRect rect;
|
||||
GstOSXWindow *osxwindow = NULL;
|
||||
GstStructure *s;
|
||||
GstMessage *msg;
|
||||
gboolean res = TRUE;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
g_return_val_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink), NULL);
|
||||
g_return_val_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink), FALSE);
|
||||
|
||||
GST_DEBUG_OBJECT (osxvideosink, "Creating new OSX window");
|
||||
|
||||
osxwindow = g_new0 (GstOSXWindow, 1);
|
||||
osxvideosink->osxwindow = osxwindow = g_new0 (GstOSXWindow, 1);
|
||||
|
||||
osxwindow->width = width;
|
||||
osxwindow->height = height;
|
||||
|
@ -97,17 +101,44 @@ gst_osx_video_sink_osxwindow_new (GstOSXVideoSink * osxvideosink, gint width,
|
|||
osxwindow->gstview =[[GstGLView alloc] initWithFrame:rect];
|
||||
|
||||
s = gst_structure_new ("have-ns-view",
|
||||
"nsview", G_TYPE_POINTER, osxwindow->gstview,
|
||||
nil);
|
||||
"nsview", G_TYPE_POINTER, osxwindow->gstview,
|
||||
nil);
|
||||
|
||||
msg = gst_message_new_element (GST_OBJECT (osxvideosink), s);
|
||||
gst_element_post_message (GST_ELEMENT (osxvideosink), msg);
|
||||
|
||||
GST_LOG_OBJECT (osxvideosink, "'have-ns-view' message sent");
|
||||
GST_INFO_OBJECT (osxvideosink, "'have-ns-view' message sent");
|
||||
|
||||
/* check if have-ns-view was handled and osxwindow->gstview was added to a
|
||||
* superview
|
||||
*/
|
||||
if ([osxwindow->gstview haveSuperview] == NO) {
|
||||
/* have-ns-view wasn't handled, post prepare-xwindow-id */
|
||||
if (osxvideosink->superview == NULL) {
|
||||
GST_INFO_OBJECT (osxvideosink, "emitting prepare-xwindow-id");
|
||||
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (osxvideosink));
|
||||
}
|
||||
|
||||
if (osxvideosink->superview != NULL) {
|
||||
/* prepare-xwindow-id was handled, we have the superview in
|
||||
* osxvideosink->superview. We now add osxwindow->gstview to the superview
|
||||
* from the main thread
|
||||
*/
|
||||
GST_INFO_OBJECT (osxvideosink, "we have a superview, adding our view to it");
|
||||
[osxwindow->gstview performSelectorOnMainThread:@selector(addToSuperview:)
|
||||
withObject:osxvideosink->superview waitUntilDone:YES];
|
||||
} else {
|
||||
/* the view wasn't added to a superview. It's possible that the
|
||||
* application handled have-ns-view, stored our view internally and is
|
||||
* going to add it to a superview later (webkit does that now).
|
||||
*/
|
||||
GST_INFO_OBJECT (osxvideosink, "no superview");
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return osxwindow;
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -119,6 +150,11 @@ gst_osx_video_sink_osxwindow_destroy (GstOSXVideoSink * osxvideosink)
|
|||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (osxvideosink->osxwindow) {
|
||||
if (osxvideosink->superview) {
|
||||
[osxvideosink->osxwindow->gstview
|
||||
performSelectorOnMainThread:@selector(removeFromSuperview:)
|
||||
withObject:(id)nil waitUntilDone:YES];
|
||||
}
|
||||
[osxvideosink->osxwindow->gstview release];
|
||||
|
||||
g_free (osxvideosink->osxwindow);
|
||||
|
@ -193,8 +229,8 @@ gst_osx_video_sink_change_state (GstElement * element,
|
|||
osxvideosink = GST_OSX_VIDEO_SINK (element);
|
||||
|
||||
GST_DEBUG_OBJECT (osxvideosink, "%s => %s",
|
||||
gst_element_state_get_name(GST_STATE_TRANSITION_CURRENT (transition)),
|
||||
gst_element_state_get_name(GST_STATE_TRANSITION_NEXT (transition)));
|
||||
gst_element_state_get_name(GST_STATE_TRANSITION_CURRENT (transition)),
|
||||
gst_element_state_get_name(GST_STATE_TRANSITION_NEXT (transition)));
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
|
@ -203,10 +239,12 @@ gst_osx_video_sink_change_state (GstElement * element,
|
|||
/* Creating our window and our image */
|
||||
GST_VIDEO_SINK_WIDTH (osxvideosink) = 320;
|
||||
GST_VIDEO_SINK_HEIGHT (osxvideosink) = 240;
|
||||
osxvideosink->osxwindow =
|
||||
gst_osx_video_sink_osxwindow_new (osxvideosink,
|
||||
if (!gst_osx_video_sink_osxwindow_create (osxvideosink,
|
||||
GST_VIDEO_SINK_WIDTH (osxvideosink),
|
||||
GST_VIDEO_SINK_HEIGHT (osxvideosink));
|
||||
GST_VIDEO_SINK_HEIGHT (osxvideosink))) {
|
||||
ret = GST_STATE_CHANGE_FAILURE;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -226,6 +264,7 @@ gst_osx_video_sink_change_state (GstElement * element,
|
|||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -298,10 +337,12 @@ gst_osx_video_sink_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_init (GstOSXVideoSink * osxvideosink)
|
||||
{
|
||||
osxvideosink->osxwindow = NULL;
|
||||
osxvideosink->superview = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -317,6 +358,17 @@ gst_osx_video_sink_base_init (gpointer g_class)
|
|||
gst_static_pad_template_get (&gst_osx_video_sink_sink_template_factory));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_finalize (GObject *object)
|
||||
{
|
||||
GstOSXVideoSink *osxvideosink = GST_OSX_VIDEO_SINK (object);
|
||||
|
||||
if (osxvideosink->superview)
|
||||
[osxvideosink->superview release];
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass)
|
||||
{
|
||||
|
@ -333,6 +385,7 @@ gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass)
|
|||
|
||||
gobject_class->set_property = gst_osx_video_sink_set_property;
|
||||
gobject_class->get_property = gst_osx_video_sink_get_property;
|
||||
gobject_class->finalize = gst_osx_video_sink_finalize;
|
||||
|
||||
gstbasesink_class->set_caps = gst_osx_video_sink_setcaps;
|
||||
gstbasesink_class->preroll = gst_osx_video_sink_show_frame;
|
||||
|
@ -351,6 +404,41 @@ gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass)
|
|||
FALSE, G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_osx_video_sink_interface_supported (GstImplementsInterface * iface, GType type)
|
||||
{
|
||||
g_assert (type == GST_TYPE_X_OVERLAY);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_interface_init (GstImplementsInterfaceClass * klass)
|
||||
{
|
||||
klass->supported = gst_osx_video_sink_interface_supported;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_set_xwindow_id (GstXOverlay * overlay, gulong window_id)
|
||||
{
|
||||
GstOSXVideoSink *osxvideosink = GST_OSX_VIDEO_SINK (overlay);
|
||||
|
||||
if (osxvideosink->superview) {
|
||||
GST_INFO_OBJECT (osxvideosink, "old xwindow id %p", osxvideosink->superview);
|
||||
[osxvideosink->superview release];
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (osxvideosink, "set xwindow id 0x%lx", window_id);
|
||||
osxvideosink->superview = [((NSView *) window_id) retain];
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_xoverlay_init (GstXOverlayClass * iface)
|
||||
{
|
||||
iface->set_xwindow_id = gst_osx_video_sink_set_xwindow_id;
|
||||
iface->expose = NULL;
|
||||
iface->handle_events = NULL;
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
/* */
|
||||
/* Public Methods */
|
||||
|
@ -381,9 +469,25 @@ gst_osx_video_sink_get_type (void)
|
|||
(GInstanceInitFunc) gst_osx_video_sink_init,
|
||||
};
|
||||
|
||||
static const GInterfaceInfo iface_info = {
|
||||
(GInterfaceInitFunc) gst_osx_video_sink_interface_init,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const GInterfaceInfo overlay_info = {
|
||||
(GInterfaceInitFunc) gst_osx_video_sink_xoverlay_init,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
osxvideosink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
|
||||
"GstOSXVideoSink", &osxvideosink_info, 0);
|
||||
|
||||
g_type_add_interface_static (osxvideosink_type,
|
||||
GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
|
||||
g_type_add_interface_static (osxvideosink_type, GST_TYPE_X_OVERLAY,
|
||||
&overlay_info);
|
||||
}
|
||||
|
||||
return osxvideosink_type;
|
||||
|
|
Loading…
Reference in a new issue