osxvideosink: implement the xoverlay interface. Fixes #618349.
This commit is contained in:
parent
bcde9fab09
commit
5f9f71b38e
@ -56,6 +56,10 @@ struct _GstOSXImage;
|
|||||||
- (void) setFullScreen: (BOOL) flag;
|
- (void) setFullScreen: (BOOL) flag;
|
||||||
- (void) reshape;
|
- (void) reshape;
|
||||||
- (void) setVideoSize: (int) w: (int) h;
|
- (void) setVideoSize: (int) w: (int) h;
|
||||||
|
- (BOOL) haveSuperview;
|
||||||
|
- (void) haveSuperviewReal: (NSMutableArray *)closure;
|
||||||
|
- (void) addToSuperview: (NSView *)superview;
|
||||||
|
- (void) removeFromSuperview: (id)unused;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -383,6 +383,37 @@
|
|||||||
[self initTextures];
|
[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 {
|
- (void) dealloc {
|
||||||
GST_LOG ("dealloc called");
|
GST_LOG ("dealloc called");
|
||||||
if (data) g_free(data);
|
if (data) g_free(data);
|
||||||
|
@ -70,6 +70,7 @@ struct _GstOSXVideoSink {
|
|||||||
/* Our element stuff */
|
/* Our element stuff */
|
||||||
GstVideoSink videosink;
|
GstVideoSink videosink;
|
||||||
GstOSXWindow *osxwindow;
|
GstOSXWindow *osxwindow;
|
||||||
|
NSView *superview;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstOSXVideoSinkClass {
|
struct _GstOSXVideoSinkClass {
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include <gst/interfaces/xoverlay.h>
|
||||||
|
|
||||||
#include "osxvideosink.h"
|
#include "osxvideosink.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -52,7 +53,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||||||
GST_STATIC_CAPS ("video/x-raw-yuv, "
|
GST_STATIC_CAPS ("video/x-raw-yuv, "
|
||||||
"framerate = (fraction) [ 0, MAX ], "
|
"framerate = (fraction) [ 0, MAX ], "
|
||||||
"width = (int) [ 1, MAX ], "
|
"width = (int) [ 1, MAX ], "
|
||||||
"height = (int) [ 1, MAX ], "
|
"height = (int) [ 1, MAX ], "
|
||||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
"format = (fourcc) YUY2")
|
"format = (fourcc) YUY2")
|
||||||
#else
|
#else
|
||||||
@ -63,27 +64,30 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ARG_0,
|
ARG_0,
|
||||||
ARG_EMBED
|
ARG_EMBED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void gst_osx_video_sink_osxwindow_destroy (GstOSXVideoSink * osxvideosink);
|
||||||
|
|
||||||
static GstVideoSinkClass *parent_class = NULL;
|
static GstVideoSinkClass *parent_class = NULL;
|
||||||
|
|
||||||
/* This function handles osx window creation */
|
/* This function handles osx window creation */
|
||||||
static GstOSXWindow *
|
static gboolean
|
||||||
gst_osx_video_sink_osxwindow_new (GstOSXVideoSink * osxvideosink, gint width,
|
gst_osx_video_sink_osxwindow_create (GstOSXVideoSink * osxvideosink, gint width,
|
||||||
gint height)
|
gint height)
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
GstOSXWindow *osxwindow = NULL;
|
GstOSXWindow *osxwindow = NULL;
|
||||||
GstStructure *s;
|
GstStructure *s;
|
||||||
GstMessage *msg;
|
GstMessage *msg;
|
||||||
|
gboolean res = TRUE;
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
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");
|
GST_DEBUG_OBJECT (osxvideosink, "Creating new OSX window");
|
||||||
|
|
||||||
osxwindow = g_new0 (GstOSXWindow, 1);
|
osxvideosink->osxwindow = osxwindow = g_new0 (GstOSXWindow, 1);
|
||||||
|
|
||||||
osxwindow->width = width;
|
osxwindow->width = width;
|
||||||
osxwindow->height = height;
|
osxwindow->height = height;
|
||||||
@ -97,17 +101,44 @@ gst_osx_video_sink_osxwindow_new (GstOSXVideoSink * osxvideosink, gint width,
|
|||||||
osxwindow->gstview =[[GstGLView alloc] initWithFrame:rect];
|
osxwindow->gstview =[[GstGLView alloc] initWithFrame:rect];
|
||||||
|
|
||||||
s = gst_structure_new ("have-ns-view",
|
s = gst_structure_new ("have-ns-view",
|
||||||
"nsview", G_TYPE_POINTER, osxwindow->gstview,
|
"nsview", G_TYPE_POINTER, osxwindow->gstview,
|
||||||
nil);
|
nil);
|
||||||
|
|
||||||
msg = gst_message_new_element (GST_OBJECT (osxvideosink), s);
|
msg = gst_message_new_element (GST_OBJECT (osxvideosink), s);
|
||||||
gst_element_post_message (GST_ELEMENT (osxvideosink), msg);
|
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];
|
[pool release];
|
||||||
|
|
||||||
return osxwindow;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -119,6 +150,11 @@ gst_osx_video_sink_osxwindow_destroy (GstOSXVideoSink * osxvideosink)
|
|||||||
pool = [[NSAutoreleasePool alloc] init];
|
pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
if (osxvideosink->osxwindow) {
|
if (osxvideosink->osxwindow) {
|
||||||
|
if (osxvideosink->superview) {
|
||||||
|
[osxvideosink->osxwindow->gstview
|
||||||
|
performSelectorOnMainThread:@selector(removeFromSuperview:)
|
||||||
|
withObject:(id)nil waitUntilDone:YES];
|
||||||
|
}
|
||||||
[osxvideosink->osxwindow->gstview release];
|
[osxvideosink->osxwindow->gstview release];
|
||||||
|
|
||||||
g_free (osxvideosink->osxwindow);
|
g_free (osxvideosink->osxwindow);
|
||||||
@ -193,8 +229,8 @@ gst_osx_video_sink_change_state (GstElement * element,
|
|||||||
osxvideosink = GST_OSX_VIDEO_SINK (element);
|
osxvideosink = GST_OSX_VIDEO_SINK (element);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (osxvideosink, "%s => %s",
|
GST_DEBUG_OBJECT (osxvideosink, "%s => %s",
|
||||||
gst_element_state_get_name(GST_STATE_TRANSITION_CURRENT (transition)),
|
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_NEXT (transition)));
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
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 */
|
/* Creating our window and our image */
|
||||||
GST_VIDEO_SINK_WIDTH (osxvideosink) = 320;
|
GST_VIDEO_SINK_WIDTH (osxvideosink) = 320;
|
||||||
GST_VIDEO_SINK_HEIGHT (osxvideosink) = 240;
|
GST_VIDEO_SINK_HEIGHT (osxvideosink) = 240;
|
||||||
osxvideosink->osxwindow =
|
if (!gst_osx_video_sink_osxwindow_create (osxvideosink,
|
||||||
gst_osx_video_sink_osxwindow_new (osxvideosink,
|
|
||||||
GST_VIDEO_SINK_WIDTH (osxvideosink),
|
GST_VIDEO_SINK_WIDTH (osxvideosink),
|
||||||
GST_VIDEO_SINK_HEIGHT (osxvideosink));
|
GST_VIDEO_SINK_HEIGHT (osxvideosink))) {
|
||||||
|
ret = GST_STATE_CHANGE_FAILURE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -226,6 +264,7 @@ gst_osx_video_sink_change_state (GstElement * element,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,10 +337,12 @@ gst_osx_video_sink_get_property (GObject * object, guint prop_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_osx_video_sink_init (GstOSXVideoSink * osxvideosink)
|
gst_osx_video_sink_init (GstOSXVideoSink * osxvideosink)
|
||||||
{
|
{
|
||||||
osxvideosink->osxwindow = NULL;
|
osxvideosink->osxwindow = NULL;
|
||||||
|
osxvideosink->superview = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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));
|
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
|
static void
|
||||||
gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass)
|
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->set_property = gst_osx_video_sink_set_property;
|
||||||
gobject_class->get_property = gst_osx_video_sink_get_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->set_caps = gst_osx_video_sink_setcaps;
|
||||||
gstbasesink_class->preroll = gst_osx_video_sink_show_frame;
|
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));
|
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 */
|
/* Public Methods */
|
||||||
@ -381,9 +469,25 @@ gst_osx_video_sink_get_type (void)
|
|||||||
(GInstanceInitFunc) gst_osx_video_sink_init,
|
(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,
|
osxvideosink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
|
||||||
"GstOSXVideoSink", &osxvideosink_info, 0);
|
"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;
|
return osxvideosink_type;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user