|
Packit |
0652a1 |
/*
|
|
Packit |
0652a1 |
* GStreamer
|
|
Packit |
0652a1 |
* Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
|
|
Packit |
0652a1 |
*
|
|
Packit |
0652a1 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
0652a1 |
* modify it under the terms of the GNU Library General Public
|
|
Packit |
0652a1 |
* License as published by the Free Software Foundation; either
|
|
Packit |
0652a1 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
0652a1 |
*
|
|
Packit |
0652a1 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
0652a1 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0652a1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0652a1 |
* Library General Public License for more details.
|
|
Packit |
0652a1 |
*
|
|
Packit |
0652a1 |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
0652a1 |
* License along with this library; if not, write to the
|
|
Packit |
0652a1 |
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
Packit |
0652a1 |
* Boston, MA 02110-1301, USA.
|
|
Packit |
0652a1 |
*/
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
#include <Cocoa/Cocoa.h>
|
|
Packit |
0652a1 |
#include <gst/gst.h>
|
|
Packit |
0652a1 |
#include <gst/video/videooverlay.h>
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
|
Packit |
0652a1 |
#define NSEventMaskAny NSAnyEventMask
|
|
Packit |
0652a1 |
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
|
Packit |
0652a1 |
#define NSWindowStyleMaskClosable NSClosableWindowMask
|
|
Packit |
0652a1 |
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
|
Packit |
0652a1 |
#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
|
|
Packit |
0652a1 |
#endif
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
/* ============================================================= */
|
|
Packit |
0652a1 |
/* */
|
|
Packit |
0652a1 |
/* MainWindow */
|
|
Packit |
0652a1 |
/* */
|
|
Packit |
0652a1 |
/* ============================================================= */
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
@interface MainWindow: NSWindow <NSApplicationDelegate> {
|
|
Packit |
0652a1 |
GMainLoop *m_loop;
|
|
Packit |
0652a1 |
GstElement *m_pipeline;
|
|
Packit |
0652a1 |
gboolean m_isClosed;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
- (id) initWithContentRect:(NSRect) contentRect Loop:(GMainLoop*)loop Pipeline:(GstElement*)pipeline;
|
|
Packit |
0652a1 |
- (GMainLoop*) loop;
|
|
Packit |
0652a1 |
- (GstElement*) pipeline;
|
|
Packit |
0652a1 |
- (gboolean) isClosed;
|
|
Packit |
0652a1 |
@end
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
@implementation MainWindow
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (id) initWithContentRect:(NSRect)contentRect Loop:(GMainLoop*)loop Pipeline:(GstElement*)pipeline
|
|
Packit |
0652a1 |
{
|
|
Packit |
0652a1 |
m_loop = loop;
|
|
Packit |
0652a1 |
m_pipeline = pipeline;
|
|
Packit |
0652a1 |
m_isClosed = FALSE;
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
self = [super initWithContentRect: contentRect
|
|
Packit |
0652a1 |
styleMask: (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
|
|
Packit |
0652a1 |
NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable)
|
|
Packit |
0652a1 |
backing: NSBackingStoreBuffered defer: NO screen: nil];
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
[self setReleasedWhenClosed:NO];
|
|
Packit |
0652a1 |
[[NSApplication sharedApplication] setDelegate:self];
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
[self setTitle:@"gst-plugins-gl implements videooverlay interface"];
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
return self;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (GMainLoop*) loop {
|
|
Packit |
0652a1 |
return m_loop;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (GstElement*) pipeline {
|
|
Packit |
0652a1 |
return m_pipeline;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (gboolean) isClosed {
|
|
Packit |
0652a1 |
return m_isClosed;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (void) customClose {
|
|
Packit |
0652a1 |
m_isClosed = TRUE;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (BOOL) windowShouldClose:(id)sender {
|
|
Packit |
0652a1 |
gst_element_send_event (m_pipeline, gst_event_new_eos ());
|
|
Packit |
0652a1 |
return YES;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (void) applicationDidFinishLaunching: (NSNotification *) not {
|
|
Packit |
0652a1 |
[self makeMainWindow];
|
|
Packit |
0652a1 |
[self center];
|
|
Packit |
0652a1 |
[self orderFront:self];
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app {
|
|
Packit |
0652a1 |
return NO;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
@end
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
/* ============================================================= */
|
|
Packit |
0652a1 |
/* */
|
|
Packit |
0652a1 |
/* gstreamer callbacks */
|
|
Packit |
0652a1 |
/* */
|
|
Packit |
0652a1 |
/* ============================================================= */
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
static GstBusSyncReply create_window (GstBus* bus, GstMessage* message, MainWindow* window)
|
|
Packit |
0652a1 |
{
|
|
Packit |
0652a1 |
// ignore anything but 'prepare-window-handle' element messages
|
|
Packit |
0652a1 |
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
|
|
Packit |
0652a1 |
return GST_BUS_PASS;
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
if (!gst_is_video_overlay_prepare_window_handle_message (message))
|
|
Packit |
0652a1 |
return GST_BUS_PASS;
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
g_print ("setting window handle %lud\n", (gulong) window);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), (guintptr) [window contentView]);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
gst_message_unref (message);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
return GST_BUS_DROP;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
static void end_stream_cb(GstBus* bus, GstMessage* message, MainWindow* window)
|
|
Packit |
0652a1 |
{
|
|
Packit |
0652a1 |
g_print ("end of stream\n");
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
gst_element_set_state ([window pipeline], GST_STATE_NULL);
|
|
Packit |
0652a1 |
gst_object_unref ([window pipeline]);
|
|
Packit |
0652a1 |
g_main_loop_quit ([window loop]);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
[window performSelectorOnMainThread:@selector(customClose) withObject:nil waitUntilDone:YES];
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
static gpointer thread_func (MainWindow* window)
|
|
Packit |
0652a1 |
{
|
|
Packit |
0652a1 |
g_main_loop_run ([window loop]);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
return NULL;
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
/* ============================================================= */
|
|
Packit |
0652a1 |
/* */
|
|
Packit |
0652a1 |
/* application */
|
|
Packit |
0652a1 |
/* */
|
|
Packit |
0652a1 |
/* ============================================================= */
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
int main(int argc, char **argv)
|
|
Packit |
0652a1 |
{
|
|
Packit |
0652a1 |
int width = 640;
|
|
Packit |
0652a1 |
int height = 480;
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
GMainLoop *loop = NULL;
|
|
Packit |
0652a1 |
GstElement *pipeline = NULL;
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
GstElement *videosrc = NULL;
|
|
Packit |
0652a1 |
GstElement *videosink = NULL;
|
|
Packit |
0652a1 |
GstCaps *caps=NULL;
|
|
Packit |
0652a1 |
gboolean ok=FALSE;
|
|
Packit |
0652a1 |
GstBus *bus=NULL;
|
|
Packit |
0652a1 |
GThread *loop_thread=NULL;
|
|
Packit |
0652a1 |
NSRect rect;
|
|
Packit |
0652a1 |
MainWindow *window=nil;
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
[NSApplication sharedApplication];
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
g_print("app created\n");
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
gst_init (&argc, &argv);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
loop = g_main_loop_new (NULL, FALSE);
|
|
Packit |
0652a1 |
pipeline = gst_pipeline_new ("pipeline");
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
videosrc = gst_element_factory_make ("videotestsrc", "videotestsrc");
|
|
Packit |
0652a1 |
videosink = gst_element_factory_make ("glimagesink", "glimagesink");
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
g_object_set(G_OBJECT(videosrc), "num-buffers", 500, NULL);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
gst_bin_add_many (GST_BIN (pipeline), videosrc, videosink, NULL);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
caps = gst_caps_new_simple("video/x-raw",
|
|
Packit |
0652a1 |
"width", G_TYPE_INT, width,
|
|
Packit |
0652a1 |
"height", G_TYPE_INT, height,
|
|
Packit |
0652a1 |
"framerate", GST_TYPE_FRACTION, 25, 1,
|
|
Packit |
0652a1 |
"format", G_TYPE_STRING, "I420",
|
|
Packit |
0652a1 |
NULL);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
ok = gst_element_link_filtered(videosrc, videosink, caps);
|
|
Packit |
0652a1 |
gst_caps_unref(caps);
|
|
Packit |
0652a1 |
if (!ok)
|
|
Packit |
0652a1 |
g_warning("could not link videosrc to videosink\n");
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
rect.origin.x = 0; rect.origin.y = 0;
|
|
Packit |
0652a1 |
rect.size.width = width; rect.size.height = height;
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
window = [[MainWindow alloc] initWithContentRect:rect Loop:loop Pipeline:pipeline];
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
|
Packit |
0652a1 |
gst_bus_add_signal_watch (bus);
|
|
Packit |
0652a1 |
/* NOTE: window is not bridge_retained because its lifetime is just this function */
|
|
Packit |
0652a1 |
g_signal_connect(bus, "message::error", G_CALLBACK(end_stream_cb), (__bridge gpointer)window);
|
|
Packit |
0652a1 |
g_signal_connect(bus, "message::warning", G_CALLBACK(end_stream_cb), (__bridge gpointer)window);
|
|
Packit |
0652a1 |
g_signal_connect(bus, "message::eos", G_CALLBACK(end_stream_cb), (__bridge gpointer)window);
|
|
Packit |
0652a1 |
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, (__bridge gpointer)window, NULL);
|
|
Packit |
0652a1 |
gst_object_unref (bus);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
loop_thread = g_thread_new (NULL,
|
|
Packit |
0652a1 |
(GThreadFunc) thread_func, (__bridge gpointer)window);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
[window orderFront:window];
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
while (![window isClosed]) {
|
|
Packit |
0652a1 |
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
|
Packit |
0652a1 |
untilDate:[NSDate dateWithTimeIntervalSinceNow:1]
|
|
Packit |
0652a1 |
inMode:NSDefaultRunLoopMode dequeue:YES];
|
|
Packit |
0652a1 |
if (event)
|
|
Packit |
0652a1 |
[NSApp sendEvent:event];
|
|
Packit |
0652a1 |
}
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
g_thread_join (loop_thread);
|
|
Packit |
0652a1 |
|
|
Packit |
0652a1 |
return 0;
|
|
Packit |
0652a1 |
}
|