3a54fe65bb5e65d1dcbad436d334c5826a2caef7
[platform/upstream/gstreamer.git] / tests / examples / gl / generic / cube / main.cpp
1 /*
2  * GStreamer
3  * Copyright (C) 2008-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 <gst/gst.h>
22 #include <gst/gl/gl.h>
23
24 #include <iostream>
25 #include <string>
26
27 static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
28 {
29     GMainLoop *loop = (GMainLoop*)data;
30
31     switch (GST_MESSAGE_TYPE (msg))
32     {
33         case GST_MESSAGE_EOS:
34               g_print ("End-of-stream\n");
35               g_main_loop_quit (loop);
36               break;
37         case GST_MESSAGE_ERROR:
38           {
39               gchar *debug = NULL;
40               GError *err = NULL;
41
42               gst_message_parse_error (msg, &err, &debug);
43
44               g_print ("Error: %s\n", err->message);
45               g_error_free (err);
46
47               if (debug)
48               {
49                   g_print ("Debug deails: %s\n", debug);
50                   g_free (debug);
51               }
52
53               g_main_loop_quit (loop);
54               break;
55           }
56         default:
57           break;
58     }
59
60     return TRUE;
61 }
62
63 //client reshape callback
64 static gboolean reshapeCallback (void *gl_sink, void *context, GLuint width, GLuint height, gpointer data)
65 {
66     glViewport(0, 0, width, height);
67     glMatrixMode(GL_PROJECTION);
68     glLoadIdentity();
69     glMatrixMode(GL_MODELVIEW);
70
71     return TRUE;
72 }
73
74 //client draw callback
75 static gboolean drawCallback (GstElement * gl_sink, GstGLContext *context, GstSample * sample, gpointer data)
76 {
77     static GLfloat      xrot = 0;
78     static GLfloat      yrot = 0;
79     static GLfloat      zrot = 0;
80     static GTimeVal current_time;
81     static glong last_sec = current_time.tv_sec;
82     static gint nbFrames = 0;
83
84     GstVideoFrame v_frame;
85     GstVideoInfo v_info;
86     guint texture = 0;
87     GstBuffer *buf = gst_sample_get_buffer (sample);
88     GstCaps *caps = gst_sample_get_caps (sample);
89
90     gst_video_info_from_caps (&v_info, caps);
91
92     if (!gst_video_frame_map (&v_frame, &v_info, buf, (GstMapFlags) (GST_MAP_READ | GST_MAP_GL))) {
93       g_warning ("Failed to map the video buffer");
94       return TRUE;
95     }
96
97     texture = *(guint *) v_frame.data[0];
98
99     g_get_current_time (&current_time);
100     nbFrames++ ;
101
102     if ((current_time.tv_sec - last_sec) >= 1)
103     {
104         std::cout << "GRPHIC FPS = " << nbFrames << std::endl;
105         nbFrames = 0;
106         last_sec = current_time.tv_sec;
107     }
108
109     glEnable(GL_DEPTH_TEST);
110
111     glEnable (GL_TEXTURE_2D);
112     glBindTexture (GL_TEXTURE_2D, texture);
113     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
114     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
115     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
116     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
117     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
118
119     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
120     glMatrixMode(GL_MODELVIEW);
121     glLoadIdentity();
122
123     glScalef(0.5f,0.5f,0.5f);
124
125     glRotatef(xrot,1.0f,0.0f,0.0f);
126     glRotatef(yrot,0.0f,1.0f,0.0f);
127     glRotatef(zrot,0.0f,0.0f,1.0f);
128
129     glBegin(GL_QUADS);
130               // Front Face
131               glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
132               glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
133               glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
134               glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
135               // Back Face
136               glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
137               glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
138               glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
139               glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
140               // Top Face
141               glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
142               glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
143               glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
144               glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
145               // Bottom Face
146               glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
147               glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
148               glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
149               glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
150               // Right face
151               glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
152               glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
153               glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
154               glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
155               // Left Face
156               glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
157               glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
158               glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
159               glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
160     glEnd();
161
162     gst_video_frame_unmap (&v_frame);
163
164     xrot+=0.3f;
165     yrot+=0.2f;
166     zrot+=0.4f;
167
168     glDisable (GL_DEPTH_TEST);
169     glDisable (GL_TEXTURE_2D);
170
171     return TRUE;
172 }
173
174
175 //gst-launch-1.0 videotestsrc num_buffers=400 ! video/x-raw, width=320, height=240 !
176 //glgraphicmaker ! glfiltercube ! video/x-raw, width=800, height=600 ! glimagesink
177 gint main (gint argc, gchar *argv[])
178 {
179     GstStateChangeReturn ret;
180     GstElement *pipeline, *videosrc, *glimagesink;
181
182     GMainLoop *loop;
183     GstBus *bus;
184
185     /* initialization */
186     gst_init (&argc, &argv);
187     loop = g_main_loop_new (NULL, FALSE);
188
189     /* create elements */
190     pipeline = gst_pipeline_new ("pipeline");
191
192     /* watch for messages on the pipeline's bus (note that this will only
193      * work like this when a GLib main loop is running) */
194     bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
195     gst_bus_add_watch (bus, bus_call, loop);
196     gst_object_unref (bus);
197
198     /* create elements */
199     videosrc = gst_element_factory_make ("videotestsrc", "videotestsrc0");
200     glimagesink  = gst_element_factory_make ("glimagesink", "glimagesink0");
201
202
203     if (!videosrc || !glimagesink)
204     {
205         g_print ("one element could not be found \n");
206         return -1;
207     }
208
209     /* change video source caps */
210     GstCaps *caps = gst_caps_new_simple("video/x-raw",
211                                         "format", G_TYPE_STRING, "RGB",
212                                         "width", G_TYPE_INT, 320,
213                                         "height", G_TYPE_INT, 240,
214                                         "framerate", GST_TYPE_FRACTION, 25, 1,
215                                         NULL) ;
216
217     /* configure elements */
218     g_object_set(G_OBJECT(videosrc), "num-buffers", 400, NULL);
219     g_signal_connect(G_OBJECT(glimagesink), "client-reshape", G_CALLBACK (reshapeCallback), NULL);
220     g_signal_connect(G_OBJECT(glimagesink), "client-draw", G_CALLBACK (drawCallback), NULL);
221
222     /* add elements */
223     gst_bin_add_many (GST_BIN (pipeline), videosrc, glimagesink, NULL);
224
225     /* link elements */
226     gboolean link_ok = gst_element_link_filtered(videosrc, glimagesink, caps) ;
227     gst_caps_unref(caps) ;
228     if(!link_ok)
229     {
230         g_warning("Failed to link videosrc to glimagesink!\n") ;
231         return -1 ;
232     }
233
234     /* run */
235     ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
236     if (ret == GST_STATE_CHANGE_FAILURE)
237     {
238         g_print ("Failed to start up pipeline!\n");
239
240         /* check if there is an error message with details on the bus */
241         GstMessage* msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
242         if (msg)
243         {
244           GError *err = NULL;
245
246           gst_message_parse_error (msg, &err, NULL);
247           g_print ("ERROR: %s\n", err->message);
248           g_error_free (err);
249           gst_message_unref (msg);
250         }
251         return -1;
252     }
253
254     g_main_loop_run (loop);
255
256     /* clean up */
257     gst_element_set_state (pipeline, GST_STATE_NULL);
258     gst_object_unref (pipeline);
259
260     return 0;
261 }