9c5fc9ad3e1337cfa01f6cdbc673440885453e67
[platform/upstream/gstreamer.git] / tests / examples / gl / cocoa / cocoa-videooverlay.m
1 /*
2  * GStreamer
3  * Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include <Cocoa/Cocoa.h>
22 #include <gst/gst.h>
23 #include <gst/video/videooverlay.h>
24
25 /* ============================================================= */
26 /*                                                               */
27 /*                          MainWindow                           */
28 /*                                                               */
29 /* ============================================================= */
30
31 @interface MainWindow: NSWindow {
32   GMainLoop *m_loop;
33   GstElement *m_pipeline;
34   gboolean m_isClosed;
35 }
36 - (id) initWithContentRect:(NSRect) contentRect Loop:(GMainLoop*)loop Pipeline:(GstElement*)pipeline;
37 - (GMainLoop*) loop;
38 - (GstElement*) pipeline;
39 - (gboolean) isClosed;
40 @end
41
42 @implementation MainWindow
43
44 - (id) initWithContentRect:(NSRect)contentRect Loop:(GMainLoop*)loop Pipeline:(GstElement*)pipeline
45 {
46   m_loop = loop;
47   m_pipeline = pipeline;
48   m_isClosed = FALSE;
49
50   self = [super initWithContentRect: contentRect
51                 styleMask: (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask)
52     backing: NSBackingStoreBuffered defer: NO screen: nil];
53
54   [self setReleasedWhenClosed:NO];
55   [NSApp setDelegate:self];
56
57   [self setTitle:@"gst-plugins-gl implements videooverlay interface"];
58
59   return self;
60 }
61
62 - (GMainLoop*) loop {
63   return m_loop;
64 }
65
66 - (GstElement*) pipeline {
67   return m_pipeline;
68 }
69
70 - (gboolean) isClosed {
71   return m_isClosed;
72 }
73
74 - (void) customClose {
75   m_isClosed = TRUE;
76 }
77
78 - (BOOL) windowShouldClose:(id)sender {
79   gst_element_send_event (m_pipeline, gst_event_new_eos ());
80   return YES;
81 }
82
83 - (void) applicationDidFinishLaunching: (NSNotification *) not {
84   [self makeMainWindow];
85   [self center];
86   [self orderFront:self];
87 }
88
89 - (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app {
90   return NO;
91 }
92
93 @end
94
95
96 /* ============================================================= */
97 /*                                                               */
98 /*                   gstreamer callbacks                         */
99 /*                                                               */
100 /* ============================================================= */
101
102
103 static GstBusSyncReply create_window (GstBus* bus, GstMessage* message, MainWindow* window)
104 {
105   // ignore anything but 'prepare-window-handle' element messages
106   if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
107     return GST_BUS_PASS;
108
109   if (!gst_is_video_overlay_prepare_window_handle_message (message))
110     return GST_BUS_PASS;
111
112   g_print ("setting window handle %lud\n", (gulong) window);
113
114   gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), (guintptr) [window contentView]);
115
116   gst_message_unref (message);
117
118   return GST_BUS_DROP;
119 }
120
121
122 static void end_stream_cb(GstBus* bus, GstMessage* message, MainWindow* window)
123 {
124   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
125
126   g_print ("end of stream\n");
127
128   gst_element_set_state ([window pipeline], GST_STATE_NULL);
129   gst_object_unref ([window pipeline]);
130   g_main_loop_quit ([window loop]);
131
132   [window performSelectorOnMainThread:@selector(customClose) withObject:nil waitUntilDone:YES];
133
134   [pool release];
135 }
136
137 static gpointer thread_func (MainWindow* window)
138 {
139   g_main_loop_run ([window loop]);
140
141   return NULL;
142 }
143
144
145 /* ============================================================= */
146 /*                                                               */
147 /*                         application                           */
148 /*                                                               */
149 /* ============================================================= */
150
151 int main(int argc, char **argv)
152 {
153         int width = 640;
154   int height = 480;
155
156   GMainLoop *loop = NULL;
157   GstElement *pipeline = NULL;
158
159   GstElement *videosrc  = NULL;
160   GstElement *videosink = NULL;
161   GstCaps *caps=NULL;
162   gboolean ok=FALSE;
163   GstBus *bus=NULL;
164   GThread *loop_thread=NULL;
165   NSAutoreleasePool *pool=nil;
166   NSRect rect;
167   MainWindow *window=nil;
168
169   g_print("app created\n");
170
171   gst_init (&argc, &argv);
172
173   loop = g_main_loop_new (NULL, FALSE);
174   pipeline = gst_pipeline_new ("pipeline");
175
176   videosrc  = gst_element_factory_make ("videotestsrc", "videotestsrc");
177   videosink = gst_element_factory_make ("glimagesink", "glimagesink");
178
179   g_object_set(G_OBJECT(videosrc), "num-buffers", 500, NULL);
180
181   gst_bin_add_many (GST_BIN (pipeline), videosrc, videosink, NULL);
182
183   caps = gst_caps_new_simple("video/x-raw",
184     "width", G_TYPE_INT, width,
185     "height", G_TYPE_INT, height,
186     "framerate", GST_TYPE_FRACTION, 25, 1,
187     "format", G_TYPE_STRING, "I420",
188     NULL);
189
190   ok = gst_element_link_filtered(videosrc, videosink, caps);
191   gst_caps_unref(caps);
192   if (!ok)
193     g_warning("could not link videosrc to videosink\n");
194
195   pool = [[NSAutoreleasePool alloc] init];
196   [NSApplication sharedApplication];
197
198   rect.origin.x = 0; rect.origin.y = 0;
199   rect.size.width = width; rect.size.height = height;
200
201   window = [[MainWindow alloc] initWithContentRect:rect Loop:loop Pipeline:pipeline];
202
203   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
204   gst_bus_add_signal_watch (bus);
205   g_signal_connect(bus, "message::error", G_CALLBACK(end_stream_cb), window);
206   g_signal_connect(bus, "message::warning", G_CALLBACK(end_stream_cb), window);
207   g_signal_connect(bus, "message::eos", G_CALLBACK(end_stream_cb), window);
208   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, window, NULL);
209   gst_object_unref (bus);
210
211   loop_thread = g_thread_new (NULL,
212       (GThreadFunc) thread_func, window);
213
214   gst_element_set_state (pipeline, GST_STATE_PLAYING);
215
216   [window orderFront:window];
217
218   while (![window isClosed]) {
219     NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
220       untilDate:[NSDate dateWithTimeIntervalSinceNow:1]
221       inMode:NSDefaultRunLoopMode dequeue:YES];
222     if (event)
223       [NSApp sendEvent:event];
224   }
225
226   g_thread_join (loop_thread);
227
228   [window release];
229
230   [pool release];
231
232   return 0;
233 }