-
-
Save gohai/dbba1c887ffde82a80ef to your computer and use it in GitHub Desktop.
Gstreamer glimagesink raspberry pi generic example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* GStreamer GLES2 Raspberry Pi example | |
* Based on http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/tests/examples/gl/generic/cube/main.cpp | |
* Modified for GStreamer 1.4.4 (Raspbian November 2015) by Gottfried Haider <[email protected]> | |
* Modified for Raspberry Pi/GLES2 by Arnaud Loonstra <[email protected]> | |
* Orginal by Julien Isorce <[email protected]> | |
* | |
* 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., 51 Franklin St, Fifth Floor, | |
* Boston, MA 02110-1301, USA. | |
*/ | |
/* Compile on a RPI with latest Gstreamer in /usr/local | |
$ g++ glesgeneric.c -pthread -I/usr/include/gstreamer-1.0 \ | |
-I/usr/include/glib-2.0 \ | |
-I/usr/lib/arm-linux-gnueabihf/glib-2.0/include \ | |
-I/usr/include/libdrm \ | |
-I/opt/vc/include/ \ | |
-I-I/opt/vc/include/interface/vcos/pthreads/ \ | |
-I/usr/local/include/gstreamer-1.0/ \ | |
-L/opt/vc/lib/ -lgstreamer-1.0 -lgobject-2.0 \ | |
-lglib-2.0 -lGLESv2 -lEGL | |
*/ | |
#include <GLES/gl.h> | |
#include <GLES2/gl2.h> | |
#include <gst/gst.h> | |
#include <gst/gl/gl.h> | |
#include <stdlib.h> | |
#include <iostream> | |
#include <string> | |
static const gchar *simple_vertex_shader_str_gles2 = | |
"attribute vec4 a_position; \n" | |
"attribute vec2 a_texCoord; \n" | |
"varying vec2 v_texCoord; \n" | |
"void main() \n" | |
"{ \n" | |
" gl_Position = a_position; \n" | |
" v_texCoord = a_texCoord; \n" | |
"} \n"; | |
static const gchar *simple_fragment_shader_str_gles2 = | |
"#ifdef GL_ES \n" | |
"precision mediump float; \n" | |
"#endif \n" | |
"varying vec2 v_texCoord; \n" | |
"uniform sampler2D tex; \n" | |
"void main() \n" | |
"{ \n" | |
" gl_FragColor = texture2D( tex, v_texCoord ); \n" | |
"} \n"; | |
GLuint vertexShader; | |
GLuint fragmentShader; | |
GLuint programObject; | |
GLint linked; | |
/// | |
// Create a shader object, load the shader source, and | |
// compile the shader. | |
// | |
GLuint LoadShader ( GLenum type, const char *shaderSrc ) | |
{ | |
GLuint shader; | |
GLint compiled; | |
// Create the shader object | |
shader = glCreateShader ( type ); | |
if ( shader == 0 ) | |
return 0; | |
// Load the shader source | |
glShaderSource ( shader, 1, &shaderSrc, NULL ); | |
// Compile the shader | |
glCompileShader ( shader ); | |
// Check the compile status | |
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); | |
if ( !compiled ) | |
{ | |
GLint infoLen = 0; | |
glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); | |
if ( infoLen > 1 ) | |
{ | |
char* infoLog = (char*)malloc (sizeof(char) * infoLen ); | |
glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); | |
std::cout << "Error compiling shader:\n" << infoLog << "\n"; | |
free ( infoLog ); | |
} | |
glDeleteShader ( shader ); | |
return 0; | |
} | |
return shader; | |
} | |
GLint initGL() { | |
// load vertext/fragment shader | |
vertexShader = LoadShader ( GL_VERTEX_SHADER, simple_vertex_shader_str_gles2 ); | |
fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, simple_fragment_shader_str_gles2 ); | |
// Create the program object | |
programObject = glCreateProgram(); | |
if ( programObject == 0 ) | |
{ | |
std::cout << "error program object\n"; | |
return 0; | |
} | |
glAttachShader(programObject, vertexShader); | |
glAttachShader(programObject, fragmentShader); | |
// Bind vPosition to attribute 0 | |
glBindAttribLocation(programObject, 0, "a_position"); | |
// Link the program | |
glLinkProgram(programObject); | |
// Check the link status | |
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); | |
if ( !linked ) | |
{ | |
GLint infoLen = 0; | |
glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); | |
if ( infoLen > 1 ) | |
{ | |
char* infoLog = (char*)malloc (sizeof(char) * infoLen ); | |
glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); | |
std::cout << "Error linking program:\n" << infoLog << "\n"; | |
free ( infoLog ); | |
} | |
glDeleteProgram ( programObject ); | |
return GL_FALSE; | |
} | |
return GL_TRUE; | |
} | |
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) | |
{ | |
GMainLoop *loop = (GMainLoop*)data; | |
switch (GST_MESSAGE_TYPE (msg)) | |
{ | |
case GST_MESSAGE_EOS: | |
g_print ("End-of-stream\n"); | |
g_main_loop_quit (loop); | |
break; | |
case GST_MESSAGE_ERROR: | |
{ | |
gchar *debug = NULL; | |
GError *err = NULL; | |
gst_message_parse_error (msg, &err, &debug); | |
g_print ("Error: %s\n", err->message); | |
g_error_free (err); | |
if (debug) | |
{ | |
g_print ("Debug deails: %s\n", debug); | |
g_free (debug); | |
} | |
g_main_loop_quit (loop); | |
break; | |
} | |
default: | |
break; | |
} | |
return TRUE; | |
} | |
//client reshape callback | |
static gboolean reshapeCallback (void *gl_sink, GLuint width, GLuint height, gpointer data) | |
{ | |
//std::cout << "Reshape: width=" << width << " height=" << height << "\n"; | |
glViewport(0, 0, width, height); | |
return TRUE; | |
} | |
//client draw callback | |
static gboolean drawCallback (void * gl_sink, GLuint texture, GLuint width, GLuint height, gpointer data) | |
{ | |
//std::cout << "draw:" << vertexShader << ":" << fragmentShader << ":" << programObject << ":" << linked << "\n"; | |
if (!linked) { | |
initGL(); | |
} | |
GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0 | |
0.0f, 0.0f, // TexCoord 0 | |
-0.5f, -0.5f, 0.0f, // Position 1 | |
0.0f, 1.0f, // TexCoord 1 | |
0.5f, -0.5f, 0.0f, // Position 2 | |
1.0f, 1.0f, // TexCoord 2 | |
0.5f, 0.5f, 0.0f, // Position 3, skewed a bit | |
1.0f, 0.0f // TexCoord 3 | |
}; | |
GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; | |
glClear ( GL_COLOR_BUFFER_BIT ); | |
glUseProgram ( programObject ); | |
// Load the vertex position | |
GLint positionLoc = glGetAttribLocation ( programObject, "a_position" ); | |
glVertexAttribPointer ( positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices ); | |
// Load the texture coordinate | |
GLint texCoordLoc = glGetAttribLocation ( programObject, "a_texCoord"); | |
glVertexAttribPointer ( texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); | |
glEnableVertexAttribArray ( positionLoc ); | |
glEnableVertexAttribArray ( texCoordLoc ); | |
glActiveTexture ( GL_TEXTURE0 ); | |
glBindTexture (GL_TEXTURE_2D, texture); | |
//Set the texture sampler to texture unit 0 | |
GLint tex = glGetUniformLocation ( programObject, "tex"); | |
glUniform1i ( tex, 0 ); | |
glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); | |
} | |
//gst-launch-1.0 videotestsrc num_buffers=400 ! video/x-raw, width=320, height=240 ! | |
//glgraphicmaker ! glfiltercube ! video/x-raw, width=800, height=600 ! glimagesink | |
gint main (gint argc, gchar *argv[]) | |
{ | |
GstStateChangeReturn ret; | |
GstElement *pipeline, *videosrc, *glimagesink; | |
GMainLoop *loop; | |
GstBus *bus; | |
/* initialization */ | |
gst_init (&argc, &argv); | |
loop = g_main_loop_new (NULL, FALSE); | |
/* create elements */ | |
pipeline = gst_pipeline_new ("pipeline"); | |
/* watch for messages on the pipeline's bus (note that this will only | |
* work like this when a GLib main loop is running) */ | |
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); | |
gst_bus_add_watch (bus, bus_call, loop); | |
gst_object_unref (bus); | |
/* create elements */ | |
videosrc = gst_element_factory_make ("videotestsrc", "videotestsrc0"); | |
glimagesink = gst_element_factory_make ("glimagesink", "glimagesink0"); | |
if (!videosrc || !glimagesink) | |
{ | |
g_print ("one element could not be found \n"); | |
return -1; | |
} | |
/* change video source caps */ | |
GstCaps *caps = gst_caps_new_simple("video/x-raw", | |
"format", G_TYPE_STRING, "RGB", | |
"width", G_TYPE_INT, 320, | |
"height", G_TYPE_INT, 240, | |
"framerate", GST_TYPE_FRACTION, 25, 1, | |
NULL) ; | |
/* configure elements */ | |
g_object_set(G_OBJECT(videosrc), "num-buffers", 400, NULL); | |
g_signal_connect(G_OBJECT(glimagesink), "client-reshape", G_CALLBACK (reshapeCallback), NULL); | |
g_signal_connect(G_OBJECT(glimagesink), "client-draw", G_CALLBACK (drawCallback), NULL); | |
/* add elements */ | |
gst_bin_add_many (GST_BIN (pipeline), videosrc, glimagesink, NULL); | |
/* link elements */ | |
gboolean link_ok = gst_element_link_filtered(videosrc, glimagesink, caps) ; | |
gst_caps_unref(caps) ; | |
if(!link_ok) | |
{ | |
g_warning("Failed to link videosrc to glimagesink!\n") ; | |
return -1 ; | |
} | |
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); | |
if (ret == GST_STATE_CHANGE_FAILURE) | |
{ | |
g_print ("Failed to start up pipeline!\n"); | |
/* check if there is an error message with details on the bus */ | |
GstMessage* msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0); | |
if (msg) | |
{ | |
GError *err = NULL; | |
gst_message_parse_error (msg, &err, NULL); | |
g_print ("ERROR: %s\n", err->message); | |
g_error_free (err); | |
gst_message_unref (msg); | |
} | |
return -1; | |
} | |
// run loop | |
g_main_loop_run (loop); | |
/* clean up */ | |
gst_element_set_state (pipeline, GST_STATE_NULL); | |
gst_object_unref (pipeline); | |
glDeleteShader(vertexShader); | |
glDeleteShader(fragmentShader); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment