int main (int argc, char **argv) { #ifdef WIN32 HGLRC sdl_gl_context = 0; HDC sdl_dc = 0; #else SDL_SysWMinfo info; Display *sdl_display = NULL; Window sdl_win = 0; GLXContext sdl_gl_context = NULL; #endif GMainLoop *loop = NULL; GstPipeline *pipeline = NULL; GstBus *bus = NULL; GstElement *glimagesink = NULL; const gchar *platform; /* Initialize SDL for video output */ if (SDL_Init (SDL_INIT_VIDEO) < 0) { fprintf (stderr, "Unable to initialize SDL: %s\n", SDL_GetError ()); return -1; } /* Create a 640x480 OpenGL screen */ if (SDL_SetVideoMode (640, 480, 0, SDL_OPENGL) == NULL) { fprintf (stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError ()); SDL_Quit (); return -1; } /* Set the title bar in environments that support it */ SDL_WM_SetCaption ("SDL and gst-plugins-gl", NULL); /* Loop, drawing and checking events */ InitGL (640, 480); gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* retrieve and turn off sdl opengl context */ #ifdef WIN32 sdl_gl_context = wglGetCurrentContext (); sdl_dc = wglGetCurrentDC (); wglMakeCurrent (0, 0); platform = "wgl"; sdl_gl_display = gst_gl_display_new (); #else SDL_VERSION (&info.version); SDL_GetWMInfo (&info); /* FIXME: This display is different to the one that SDL uses to create the * GL context inside SDL_SetVideoMode() above which fails on Intel hardware */ sdl_display = info.info.x11.gfxdisplay; sdl_win = info.info.x11.window; sdl_gl_context = glXGetCurrentContext (); glXMakeCurrent (sdl_display, None, 0); platform = "glx"; sdl_gl_display = (GstGLDisplay *) gst_gl_display_x11_new_with_display (sdl_display); #endif sdl_context = gst_gl_context_new_wrapped (sdl_gl_display, (guintptr) sdl_gl_context, gst_gl_platform_from_string (platform), GST_GL_API_OPENGL); pipeline = GST_PIPELINE (gst_parse_launch ("videotestsrc ! video/x-raw, width=320, height=240, framerate=(fraction)30/1 ! " "glimagesink name=glimagesink0", NULL)); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_signal_watch (bus); g_signal_connect (bus, "message::error", G_CALLBACK (end_stream_cb), loop); g_signal_connect (bus, "message::warning", G_CALLBACK (end_stream_cb), loop); g_signal_connect (bus, "message::eos", G_CALLBACK (end_stream_cb), loop); gst_bus_enable_sync_message_emission (bus); g_signal_connect (bus, "sync-message", G_CALLBACK (sync_bus_call), NULL); gst_object_unref (bus); glimagesink = gst_bin_get_by_name (GST_BIN (pipeline), "glimagesink0"); g_signal_connect (G_OBJECT (glimagesink), "client-draw", G_CALLBACK (on_client_draw), NULL); gst_object_unref (glimagesink); /* NULL to PAUSED state pipeline to make sure the gst opengl context is created and * shared with the sdl one */ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); /* turn on back sdl opengl context */ #ifdef WIN32 wglMakeCurrent (sdl_dc, sdl_gl_context); #else glXMakeCurrent (sdl_display, sdl_win, sdl_gl_context); #endif gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); g_timeout_add (100, update_sdl_scene, pipeline); g_main_loop_run (loop); /* before to deinitialize the gst-gl-opengl context, * no shared context (here the sdl one) must be current */ #ifdef WIN32 wglMakeCurrent (0, 0); #else glXMakeCurrent (sdl_display, sdl_win, sdl_gl_context); #endif gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); gst_object_unref (pipeline); /* turn on back sdl opengl context */ #ifdef WIN32 wglMakeCurrent (sdl_dc, sdl_gl_context); #else glXMakeCurrent (sdl_display, None, 0); #endif SDL_Quit (); return 0; }
static gboolean gst_gl_mixer_decide_allocation (GstGLMixer * mix, GstQuery * query) { GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix); GstBufferPool *pool = NULL; GstStructure *config; GstCaps *caps; guint min, max, size; gboolean update_pool; GError *error = NULL; guint idx; guint out_width, out_height; GstGLContext *other_context = NULL; GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix); gst_query_parse_allocation (query, &caps, NULL); if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); update_pool = TRUE; } else { GstVideoInfo vinfo; gst_video_info_init (&vinfo); gst_video_info_from_caps (&vinfo, caps); size = vinfo.size; min = max = 0; update_pool = FALSE; } if (!gst_gl_ensure_display (mix, &mix->display)) return FALSE; if (gst_query_find_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, &idx)) { GstGLContext *context; const GstStructure *upload_meta_params; gpointer handle; gchar *type; gchar *apis; gst_query_parse_nth_allocation_meta (query, idx, &upload_meta_params); if (upload_meta_params) { if (gst_structure_get (upload_meta_params, "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, &context, NULL) && context) { GstGLContext *old = mix->context; mix->context = context; if (old) gst_object_unref (old); } else if (gst_structure_get (upload_meta_params, "gst.gl.context.handle", G_TYPE_POINTER, &handle, "gst.gl.context.type", G_TYPE_STRING, &type, "gst.gl.context.apis", G_TYPE_STRING, &apis, NULL) && handle) { GstGLPlatform platform = GST_GL_PLATFORM_NONE; GstGLAPI gl_apis; GST_DEBUG ("got GL context handle 0x%p with type %s and apis %s", handle, type, apis); platform = gst_gl_platform_from_string (type); gl_apis = gst_gl_api_from_string (apis); if (gl_apis && platform) other_context = gst_gl_context_new_wrapped (mix->display, (guintptr) handle, platform, gl_apis); } } } if (!mix->context) { mix->context = gst_gl_context_new (mix->display); if (!gst_gl_context_create (mix->context, other_context, &error)) goto context_error; } out_width = GST_VIDEO_INFO_WIDTH (&vagg->info); out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info); g_mutex_lock (&mix->priv->gl_resource_lock); mix->priv->gl_resource_ready = FALSE; if (mix->fbo) { gst_gl_context_del_fbo (mix->context, mix->fbo, mix->depthbuffer); mix->fbo = 0; mix->depthbuffer = 0; } if (!gst_gl_context_gen_fbo (mix->context, out_width, out_height, &mix->fbo, &mix->depthbuffer)) { g_cond_signal (&mix->priv->gl_resource_cond); g_mutex_unlock (&mix->priv->gl_resource_lock); goto context_error; } if (mix->out_tex_id) gst_gl_context_del_texture (mix->context, &mix->out_tex_id); gst_gl_context_gen_texture (mix->context, &mix->out_tex_id, GST_VIDEO_FORMAT_RGBA, out_width, out_height); if (mixer_class->set_caps) mixer_class->set_caps (mix, caps); mix->priv->gl_resource_ready = TRUE; g_cond_signal (&mix->priv->gl_resource_cond); g_mutex_unlock (&mix->priv->gl_resource_lock); if (!pool) pool = gst_gl_buffer_pool_new (mix->context); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min, max); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); gst_buffer_pool_set_config (pool, config); if (update_pool) gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); else gst_query_add_allocation_pool (query, pool, size, min, max); gst_object_unref (pool); return TRUE; context_error: { GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return FALSE; } }
int main (int argc, char **argv) { #ifdef WIN32 HGLRC sdl_gl_context = 0; HDC sdl_dc = 0; #else SDL_SysWMinfo info; Display *sdl_display = NULL; Window sdl_win = 0; GLXContext sdl_gl_context = NULL; #endif GMainLoop *loop = NULL; GstPipeline *pipeline = NULL; GstBus *bus = NULL; GstElement *fakesink = NULL; GstState state; GAsyncQueue *queue_input_buf = NULL; GAsyncQueue *queue_output_buf = NULL; const gchar *platform; /* Initialize SDL for video output */ if (SDL_Init (SDL_INIT_VIDEO) < 0) { fprintf (stderr, "Unable to initialize SDL: %s\n", SDL_GetError ()); return -1; } /* Create a 640x480 OpenGL screen */ if (SDL_SetVideoMode (640, 480, 0, SDL_OPENGL) == NULL) { fprintf (stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError ()); SDL_Quit (); return -1; } /* Set the title bar in environments that support it */ SDL_WM_SetCaption ("SDL and gst-plugins-gl", NULL); /* Loop, drawing and checking events */ InitGL (640, 480); gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* retrieve and turn off sdl opengl context */ #ifdef WIN32 sdl_gl_context = wglGetCurrentContext (); sdl_dc = wglGetCurrentDC (); wglMakeCurrent (0, 0); platform = "wgl"; sdl_gl_display = gst_gl_display_new (); #else SDL_VERSION (&info.version); SDL_GetWMInfo (&info); /* FIXME: This display is different to the one that SDL uses to create the * GL context inside SDL_SetVideoMode() above which fails on Intel hardware */ sdl_display = info.info.x11.gfxdisplay; sdl_win = info.info.x11.window; sdl_gl_context = glXGetCurrentContext (); glXMakeCurrent (sdl_display, None, 0); platform = "glx"; sdl_gl_display = (GstGLDisplay *) gst_gl_display_x11_new_with_display (sdl_display); #endif sdl_context = gst_gl_context_new_wrapped (sdl_gl_display, (guintptr) sdl_gl_context, gst_gl_platform_from_string (platform), GST_GL_API_OPENGL); pipeline = GST_PIPELINE (gst_parse_launch ("videotestsrc ! video/x-raw, width=320, height=240, framerate=(fraction)30/1 ! " "gleffects effect=5 ! fakesink sync=1", NULL)); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_signal_watch (bus); g_signal_connect (bus, "message::error", G_CALLBACK (end_stream_cb), loop); g_signal_connect (bus, "message::warning", G_CALLBACK (end_stream_cb), loop); g_signal_connect (bus, "message::eos", G_CALLBACK (end_stream_cb), loop); gst_bus_enable_sync_message_emission (bus); g_signal_connect (bus, "sync-message", G_CALLBACK (sync_bus_call), NULL); gst_object_unref (bus); /* NULL to PAUSED state pipeline to make sure the gst opengl context is created and * shared with the sdl one */ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); state = GST_STATE_PAUSED; if (gst_element_get_state (GST_ELEMENT (pipeline), &state, NULL, GST_CLOCK_TIME_NONE) != GST_STATE_CHANGE_SUCCESS) { g_debug ("failed to pause pipeline\n"); return -1; } /* turn on back sdl opengl context */ #ifdef WIN32 wglMakeCurrent (sdl_dc, sdl_gl_context); #else glXMakeCurrent (sdl_display, sdl_win, sdl_gl_context); #endif /* append a gst-gl texture to this queue when you do not need it no more */ fakesink = gst_bin_get_by_name (GST_BIN (pipeline), "fakesink0"); g_object_set (G_OBJECT (fakesink), "signal-handoffs", TRUE, NULL); g_signal_connect (fakesink, "handoff", G_CALLBACK (on_gst_buffer), NULL); queue_input_buf = g_async_queue_new (); queue_output_buf = g_async_queue_new (); g_object_set_data (G_OBJECT (fakesink), "queue_input_buf", queue_input_buf); g_object_set_data (G_OBJECT (fakesink), "queue_output_buf", queue_output_buf); g_object_set_data (G_OBJECT (fakesink), "loop", loop); gst_object_unref (fakesink); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); g_main_loop_run (loop); /* before to deinitialize the gst-gl-opengl context, * no shared context (here the sdl one) must be current */ #ifdef WIN32 wglMakeCurrent (0, 0); #else glXMakeCurrent (sdl_display, sdl_win, sdl_gl_context); #endif gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); gst_object_unref (pipeline); /* turn on back sdl opengl context */ #ifdef WIN32 wglMakeCurrent (sdl_dc, sdl_gl_context); #else glXMakeCurrent (sdl_display, None, 0); #endif SDL_Quit (); /* make sure there is no pending gst gl buffer in the communication queues * between sdl and gst-gl */ while (g_async_queue_length (queue_input_buf) > 0) { GstBuffer *buf = (GstBuffer *) g_async_queue_pop (queue_input_buf); gst_buffer_unref (buf); } while (g_async_queue_length (queue_output_buf) > 0) { GstBuffer *buf = (GstBuffer *) g_async_queue_pop (queue_output_buf); gst_buffer_unref (buf); } return 0; }