3 * Copyright (C) 2008-2009 Julien Isorce <julien.isorce@gmail.com>
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.
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.
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.
24 #include <gst/gl/gstglfuncs.h>
26 #include <gst/video/video.h>
31 static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
33 GMainLoop *loop = (GMainLoop*)data;
35 switch (GST_MESSAGE_TYPE (msg))
38 g_print ("End-of-stream\n");
39 g_main_loop_quit (loop);
41 case GST_MESSAGE_ERROR:
46 gst_message_parse_error (msg, &err, &debug);
48 g_print ("Error: %s\n", err->message);
53 g_print ("Debug details: %s\n", debug);
57 g_main_loop_quit (loop);
67 //client draw callback
68 static gboolean drawCallback (void *filter, void *context, GLuint texture, GLuint width, GLuint height, gpointer data)
70 static GLfloat xrot = 0;
71 static GLfloat yrot = 0;
72 static GLfloat zrot = 0;
73 static GstClockTime current_time;
74 static GstClockTime last_time = gst_util_get_timestamp();
75 static gint nbFrames = 0;
77 current_time = gst_util_get_timestamp ();
80 if ((current_time - last_time) >= GST_SECOND)
82 std::cout << "GRAPHIC FPS = " << nbFrames << std::endl;
84 last_time = current_time;
87 glEnable(GL_DEPTH_TEST);
89 glEnable (GL_TEXTURE_2D);
90 glBindTexture (GL_TEXTURE_2D, texture);
91 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
92 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
93 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
94 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
95 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
97 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
98 glMatrixMode(GL_MODELVIEW);
101 glTranslatef(0.0f,0.0f,-5.0f);
103 glRotatef(xrot,1.0f,0.0f,0.0f);
104 glRotatef(yrot,0.0f,1.0f,0.0f);
105 glRotatef(zrot,0.0f,0.0f,1.0f);
110 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
111 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
112 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
113 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
115 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
116 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
117 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
118 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
120 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
121 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
122 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
123 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
125 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
126 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
127 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
128 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
130 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
131 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
132 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
133 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
135 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
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);
145 //return TRUE because we dealt with the texture
150 //equivalent command line:
151 //gst-launch-1.0 videotestsrc num_buffers=400 ! gleffects effect=0 !
152 //avenc_mpeg4 ! avimux ! filesink location="record.avi"
154 //gst-launch-1.0 videotestsrc num_buffers=400 ! gleffects effect=0 ! "video/x-raw, width=320, height=240" ! glfiltercube ! "video/x-raw, width=720, height=576" !
155 //avenc_mpeg4 ! avimux ! filesink location="record.avi"
156 gint main (gint argc, gchar *argv[])
158 GstStateChangeReturn ret;
159 GstElement *pipeline, *videosrc, *glfilterapp, *avenc_mpeg4, *avimux, *filesink;
164 gst_init (&argc, &argv);
165 loop = g_main_loop_new (NULL, FALSE);
167 /* create elements */
168 pipeline = gst_pipeline_new ("pipeline");
170 /* watch for messages on the pipeline's bus (note that this will only
171 * work like this when a GLib main loop is running) */
172 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
173 gst_bus_add_watch (bus, bus_call, loop);
174 gst_object_unref (bus);
176 /* create elements */
177 videosrc = gst_element_factory_make ("videotestsrc", "videotestsrc0");
178 glfilterapp = gst_element_factory_make ("glfilterapp", "glfilterapp0");
179 avenc_mpeg4 = gst_element_factory_make ("avenc_mpeg4", "avenc_mpeg40");
180 avimux = gst_element_factory_make ("avimux", "avimux0");
181 filesink = gst_element_factory_make ("filesink", "filesink0");
184 if (!videosrc || !glfilterapp || !avenc_mpeg4 || !avimux || !filesink)
186 g_print ("one element could not be found \n");
190 /* change video source caps */
191 GstCaps *caps = gst_caps_new_simple("video/x-raw",
192 "format", G_TYPE_STRING, "UYVY",
193 "width", G_TYPE_INT, 320,
194 "height", G_TYPE_INT, 240,
195 "framerate", GST_TYPE_FRACTION, 25, 1,
198 /* change video source caps */
199 GstCaps *outcaps = gst_caps_new_simple("video/x-raw",
200 "width", G_TYPE_INT, 640,
201 "height", G_TYPE_INT, 480,
204 /* configure elements */
205 g_object_set(G_OBJECT(videosrc), "num-buffers", 400, NULL);
206 g_signal_connect(G_OBJECT(glfilterapp), "client-draw", G_CALLBACK (drawCallback), NULL);
207 g_object_set(G_OBJECT(filesink), "location", "record.avi", NULL);
210 gst_bin_add_many (GST_BIN (pipeline), videosrc, glfilterapp,
211 avenc_mpeg4, avimux, filesink, NULL);
214 gboolean link_ok = gst_element_link_filtered(videosrc, glfilterapp, caps) ;
215 gst_caps_unref(caps) ;
218 g_warning("Failed to link videosrc to glfilterapp!\n") ;
222 link_ok = gst_element_link_filtered(glfilterapp, avenc_mpeg4, outcaps) ;
223 gst_caps_unref(outcaps) ;
226 g_warning("Failed to link glfilterapp to avenc_mpeg4!\n") ;
229 if (!gst_element_link_many(avenc_mpeg4, avimux, filesink, NULL))
231 g_print ("Failed to link one or more elements!\n");
237 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
238 if (ret == GST_STATE_CHANGE_FAILURE)
240 g_print ("Failed to start up pipeline!\n");
242 /* check if there is an error message with details on the bus */
243 GstMessage* msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
248 gst_message_parse_error (msg, &err, NULL);
249 g_print ("ERROR: %s\n", err->message);
251 gst_message_unref (msg);
256 g_main_loop_run (loop);
259 gst_element_set_state (pipeline, GST_STATE_NULL);
260 gst_object_unref (pipeline);