diff options
Diffstat (limited to 'sys/osxvideo/osxvideosink.m')
-rw-r--r-- | sys/osxvideo/osxvideosink.m | 665 |
1 files changed, 0 insertions, 665 deletions
diff --git a/sys/osxvideo/osxvideosink.m b/sys/osxvideo/osxvideosink.m deleted file mode 100644 index 2bb0447b..00000000 --- a/sys/osxvideo/osxvideosink.m +++ /dev/null @@ -1,665 +0,0 @@ -/* GStreamer - * OSX video sink - * Copyright (C) 2004-6 Zaheer Abbas Merali <zaheerabbas at merali dot org> - * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * The development of this code was made possible due to the involvement of - * Pioneers of the Inevitable, the creators of the Songbird Music player. - * - */ - -/** - * SECTION:element-osxvideosink - * - * <refsect2> - * <para> - * The OSXVideoSink renders video frames to a MacOSX window. The video output - * can be directed to a window embedded in an existing NSApp. This can be done - * by setting the "embed" property to #TRUE. When the NSView to be embedded is - * created an element #GstMessage with a name of 'have-ns-view' will be created - * and posted on the bus. The pointer to the NSView to embed will be in the - * 'nsview' field of that message. If no embedding is requested, the plugin will - * create a standalone window. - * </para> - * <title>Examples</title> - * <para> - * Simple timeline to test the sink : - * <programlisting> - * gst-launch-0.10 -v videotestsrc ! osxvideosink - * </programlisting> - * </para> - * </refsect2> - */ - -#include "config.h" - -/* Object header */ -#include "osxvideosink.h" -#include <unistd.h> -#import "cocoawindow.h" - -/* Debugging category */ -GST_DEBUG_CATEGORY (gst_debug_osx_video_sink); -#define GST_CAT_DEFAULT gst_debug_osx_video_sink - -/* ElementFactory information */ -static const GstElementDetails gst_osx_video_sink_details = -GST_ELEMENT_DETAILS ("OSX Video sink", - "Sink/Video", - "OSX native videosink", - "Zaheer Abbas Merali <zaheerabbas at merali dot org>"); - -/* Default template - initiated with class struct to allow gst-register to work - without X running */ -static GstStaticPadTemplate gst_osx_video_sink_sink_template_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv, " - "framerate = (fraction) [ 0, MAX ], " - "width = (int) [ 1, MAX ], " - "height = (int) [ 1, MAX ], " -#if G_BYTE_ORDER == G_BIG_ENDIAN - "format = (fourcc) YUY2") -#else - "format = (fourcc) UYVY") -#endif - ); - -// much of the following cocoa NSApp code comes from libsdl and libcaca -@implementation NSApplication(Gst) -- (void)setRunning -{ - _running = 1; -} -@end - -@implementation GstAppDelegate : NSObject -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ - // destroy stuff here! - GST_DEBUG("Kill me please!"); - return NSTerminateNow; -} -@end - - -enum -{ - ARG_0, - ARG_EMBED, - ARG_FULLSCREEN - /* FILL ME */ -}; - -static GstVideoSinkClass *parent_class = NULL; - - -/* cocoa event loop - needed if not run in own app */ -gint -cocoa_event_loop (GstOSXVideoSink * vsink) -{ - NSAutoreleasePool *pool; - gboolean ret = TRUE; - - GST_DEBUG_OBJECT (vsink, "Entering event loop"); - - pool = [[NSAutoreleasePool alloc] init]; - - if ([NSApp isRunning]) { - NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode dequeue:YES ]; - if ( event != nil ) { - switch ([event type]) { - default: //XXX Feed me please - [NSApp sendEvent:event]; - break; - } - } - } - - [pool release]; - - GST_DEBUG_OBJECT (vsink, "Leaving event loop with ret : %d", ret); - - return ret; -} - -static NSString * -GetApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -static void -CreateApplicationMenus(void) -{ - NSString *appName; - NSString *title; - NSMenu *appleMenu; - NSMenu *windowMenu; - NSMenuItem *menuItem; - - /* Create the main menu bar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - - /* Create the application menu */ - appName = GetApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@/*"h"*/""]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@/*"h"*/""]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@/*"q"*/""]; - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - [menuItem release]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - [appleMenu release]; - - - /* Create the window menu */ - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@/*"m"*/""]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:menuItem]; - [menuItem release]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - [windowMenu release]; -} - -/* This function handles osx window creation */ -static GstOSXWindow * -gst_osx_video_sink_osxwindow_new (GstOSXVideoSink * osxvideosink, gint width, - gint height) -{ - NSRect rect; - - GstOSXWindow *osxwindow = NULL; - - g_return_val_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink), NULL); - - osxwindow = g_new0 (GstOSXWindow, 1); - - osxwindow->width = width; - osxwindow->height = height; - osxwindow->internal = TRUE; - osxwindow->pool = [[NSAutoreleasePool alloc] init]; - - if (osxvideosink->embed == FALSE) { - ProcessSerialNumber psn; - unsigned int mask = NSTitledWindowMask | - NSClosableWindowMask | - NSResizableWindowMask | - NSTexturedBackgroundWindowMask | - NSMiniaturizableWindowMask; - - rect.origin.x = 100.0; - rect.origin.y = 100.0; - rect.size.width = (float) osxwindow->width; - rect.size.height = (float) osxwindow->height; - - if (!GetCurrentProcess(&psn)) { - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess(&psn); - } - - [NSApplication sharedApplication]; - - osxwindow->win =[[GstOSXVideoSinkWindow alloc] - initWithContentRect: rect - styleMask: mask - backing: NSBackingStoreBuffered - defer: NO - screen: nil]; - [osxwindow->win autorelease]; - [NSApplication sharedApplication]; - [osxwindow->win makeKeyAndOrderFront:NSApp]; - osxwindow->gstview =[osxwindow->win gstView]; - [osxwindow->gstview autorelease]; - if (osxvideosink->fullscreen) - [osxwindow->gstview setFullScreen:YES]; - - CreateApplicationMenus(); - - [NSApp finishLaunching]; - [NSApp setDelegate:[[GstAppDelegate alloc] init]]; - - [NSApp setRunning]; - // insert event dispatch in the glib main loop - g_idle_add ((GSourceFunc) cocoa_event_loop, osxvideosink); - } else { - GstStructure *s; - GstMessage *msg; - gchar * tmp; - /* Needs to be embedded */ - - rect.origin.x = 0.0; - rect.origin.y = 0.0; - rect.size.width = (float) osxwindow->width; - rect.size.height = (float) osxwindow->height; - osxwindow->gstview =[[GstGLView alloc] initWithFrame:rect]; - [osxwindow->gstview autorelease]; - - s = gst_structure_new ("have-ns-view", - "nsview", G_TYPE_POINTER, osxwindow->gstview, - nil); - - tmp = gst_structure_to_string (s); - GST_DEBUG_OBJECT (osxvideosink, "Sending message %s", - tmp); - g_free (tmp); - - 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"); - } - return osxwindow; -} - -/* This function destroys a GstXWindow */ -static void -gst_osx_video_sink_osxwindow_destroy (GstOSXVideoSink * osxvideosink, - GstOSXWindow * osxwindow) -{ - g_return_if_fail (osxwindow != NULL); - g_return_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink)); - - [osxwindow->pool release]; - - g_free (osxwindow); -} - -/* This function resizes a GstXWindow */ -static void -gst_osx_video_sink_osxwindow_resize (GstOSXVideoSink * osxvideosink, - GstOSXWindow * osxwindow, guint width, guint height) -{ - NSSize size; - NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init]; - g_return_if_fail (osxwindow != NULL); - g_return_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink)); - - osxwindow->width = width; - osxwindow->height = height; - - size.width = width; - size.height = height; - /* Call relevant cocoa function to resize window */ - [osxwindow->win setContentSize:size]; - [subPool release]; -} - -static void -gst_osx_video_sink_osxwindow_clear (GstOSXVideoSink * osxvideosink, - GstOSXWindow * osxwindow) -{ - - g_return_if_fail (osxwindow != NULL); - g_return_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink)); - -} - - -/* Element stuff */ -static gboolean -gst_osx_video_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) -{ - GstOSXVideoSink *osxvideosink; - GstStructure *structure; - gboolean res, result = FALSE; - gint video_width, video_height; - const GValue *framerate; - - osxvideosink = GST_OSX_VIDEO_SINK (bsink); - - GST_DEBUG_OBJECT (osxvideosink, "caps: %" GST_PTR_FORMAT, caps); - - structure = gst_caps_get_structure (caps, 0); - res = gst_structure_get_int (structure, "width", &video_width); - res &= gst_structure_get_int (structure, "height", &video_height); - framerate = gst_structure_get_value (structure, "framerate"); - res &= (framerate != NULL); - - if (!res) { - goto beach; - } - - osxvideosink->fps_n = gst_value_get_fraction_numerator (framerate); - osxvideosink->fps_d = gst_value_get_fraction_denominator (framerate); - - GST_DEBUG_OBJECT (osxvideosink, "our format is: %dx%d video at %d/%d fps", - video_width, video_height, osxvideosink->fps_n, osxvideosink->fps_d); - - GST_VIDEO_SINK_WIDTH (osxvideosink) = video_width; - GST_VIDEO_SINK_HEIGHT (osxvideosink) = video_height; - - gst_osx_video_sink_osxwindow_resize (osxvideosink, osxvideosink->osxwindow, - video_width, video_height); - result = TRUE; - -beach: - return result; - -} - -static GstStateChangeReturn -gst_osx_video_sink_change_state (GstElement * element, - GstStateChange transition) -{ - GstOSXVideoSink *osxvideosink; - - 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))); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - /* Creating our window and our image */ - if (!osxvideosink->osxwindow) { - GST_VIDEO_SINK_WIDTH (osxvideosink) = 320; - GST_VIDEO_SINK_HEIGHT (osxvideosink) = 240; - osxvideosink->osxwindow = - gst_osx_video_sink_osxwindow_new (osxvideosink, - GST_VIDEO_SINK_WIDTH (osxvideosink), - GST_VIDEO_SINK_HEIGHT (osxvideosink)); - gst_osx_video_sink_osxwindow_clear (osxvideosink, - osxvideosink->osxwindow); - } else { - if (osxvideosink->osxwindow->internal) - gst_osx_video_sink_osxwindow_resize (osxvideosink, - osxvideosink->osxwindow, GST_VIDEO_SINK_WIDTH (osxvideosink), - GST_VIDEO_SINK_HEIGHT (osxvideosink)); - } - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG ("ready to paused"); - if (osxvideosink->osxwindow) - gst_osx_video_sink_osxwindow_clear (osxvideosink, - osxvideosink->osxwindow); - osxvideosink->time = 0; - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - osxvideosink->fps_n = 0; - osxvideosink->fps_d = 0; - osxvideosink->sw_scaling_failed = FALSE; - GST_VIDEO_SINK_WIDTH (osxvideosink) = 0; - GST_VIDEO_SINK_HEIGHT (osxvideosink) = 0; - break; - case GST_STATE_CHANGE_READY_TO_NULL: - - if (osxvideosink->osxwindow) { - gst_osx_video_sink_osxwindow_destroy (osxvideosink, - osxvideosink->osxwindow); - osxvideosink->osxwindow = NULL; - } - break; - } - - return (GST_ELEMENT_CLASS (parent_class))->change_state (element, transition); - -} - -static GstFlowReturn -gst_osx_video_sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) -{ - GstOSXVideoSink *osxvideosink; - - osxvideosink = GST_OSX_VIDEO_SINK (bsink); - - char *viewdata =[osxvideosink->osxwindow->gstview getTextureBuffer]; - - GST_DEBUG ("show_frame"); - memcpy (viewdata, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); - [osxvideosink->osxwindow->gstview displayTexture]; - - return GST_FLOW_OK; -} - -/* Buffer management */ - - - -/* =========================================== */ -/* */ -/* Init & Class init */ -/* */ -/* =========================================== */ - -static void -gst_osx_video_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstOSXVideoSink *osxvideosink; - - g_return_if_fail (GST_IS_OSX_VIDEO_SINK (object)); - - osxvideosink = GST_OSX_VIDEO_SINK (object); - - switch (prop_id) { - case ARG_EMBED: - osxvideosink->embed = g_value_get_boolean (value); - break; - case ARG_FULLSCREEN: - osxvideosink->fullscreen = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_osx_video_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstOSXVideoSink *osxvideosink; - - g_return_if_fail (GST_IS_OSX_VIDEO_SINK (object)); - - osxvideosink = GST_OSX_VIDEO_SINK (object); - - switch (prop_id) { - case ARG_EMBED: - g_value_set_boolean (value, osxvideosink->embed); - break; - case ARG_FULLSCREEN: - g_value_set_boolean (value, osxvideosink->fullscreen); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_osx_video_sink_init (GstOSXVideoSink * osxvideosink) -{ - - osxvideosink->osxwindow = NULL; - - osxvideosink->fps_n = 0; - osxvideosink->fps_d = 0; - - osxvideosink->pixel_width = osxvideosink->pixel_height = 1; - osxvideosink->sw_scaling_failed = FALSE; - osxvideosink->embed = FALSE; - osxvideosink->fullscreen = FALSE; - -} - -static void -gst_osx_video_sink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details (element_class, &gst_osx_video_sink_details); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_osx_video_sink_sink_template_factory)); -} - -static void -gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - - - parent_class = g_type_class_ref (GST_TYPE_VIDEO_SINK); - - gobject_class->set_property = gst_osx_video_sink_set_property; - gobject_class->get_property = gst_osx_video_sink_get_property; - - gstbasesink_class->set_caps = gst_osx_video_sink_setcaps; - gstbasesink_class->preroll = gst_osx_video_sink_show_frame; - gstbasesink_class->render = gst_osx_video_sink_show_frame; - gstelement_class->change_state = gst_osx_video_sink_change_state; - - /** - * GstOSXVideoSink:embed - * - * Set to #TRUE if you are embedding the video window in an application. - * - **/ - - g_object_class_install_property (gobject_class, ARG_EMBED, - g_param_spec_boolean ("embed", "embed", "When enabled, it " - "can be embedded", FALSE, G_PARAM_READWRITE)); - - /** - * GstOSXVideoSink:fullscreen - * - * Set to #TRUE to have the video displayed in fullscreen. - **/ - - g_object_class_install_property (gobject_class, ARG_FULLSCREEN, - g_param_spec_boolean ("fullscreen", "fullscreen", - "When enabled, the view " "is fullscreen", FALSE, - G_PARAM_READWRITE)); -} - -/* ============================================================= */ -/* */ -/* Public Methods */ -/* */ -/* ============================================================= */ - -/* =========================================== */ -/* */ -/* Object typing & Creation */ -/* */ -/* =========================================== */ - -GType -gst_osx_video_sink_get_type (void) -{ - static GType osxvideosink_type = 0; - - if (!osxvideosink_type) { - static const GTypeInfo osxvideosink_info = { - sizeof (GstOSXVideoSinkClass), - gst_osx_video_sink_base_init, - NULL, - (GClassInitFunc) gst_osx_video_sink_class_init, - NULL, - NULL, - sizeof (GstOSXVideoSink), - 0, - (GInstanceInitFunc) gst_osx_video_sink_init, - }; - - osxvideosink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, - "GstOSXVideoSink", &osxvideosink_info, 0); - - } - - return osxvideosink_type; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - - if (!gst_element_register (plugin, "osxvideosink", - GST_RANK_PRIMARY, GST_TYPE_OSX_VIDEO_SINK)) - return FALSE; - - GST_DEBUG_CATEGORY_INIT (gst_debug_osx_video_sink, "osxvideosink", 0, - "osxvideosink element"); - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "osxvideo", - "OSX native video output plugin", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) |