From e6633182f3305804de97cf8ec5e00c097d4e4a79 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 20 Sep 2013 09:34:37 +0200 Subject: examples: use dedicated thread for rendering the scene Produces smother animation and prevents dropping frames due busy mainloop. --- examples/egl/testegl.c | 152 +++++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 75 deletions(-) diff --git a/examples/egl/testegl.c b/examples/egl/testegl.c index 617b547..b9833dd 100644 --- a/examples/egl/testegl.c +++ b/examples/egl/testegl.c @@ -139,7 +139,6 @@ typedef struct uint32_t screen_width; uint32_t screen_height; gboolean animate; - gboolean sync_animation_with_video; /* OpenGL|ES objects */ EGLDisplay display; @@ -179,6 +178,9 @@ typedef struct GstBuffer *last_buffer; GstCaps *current_caps; + + /* Rendering thread state */ + gboolean running; } APP_STATE_T; typedef struct @@ -933,14 +935,14 @@ init_textures (APP_STATE_T * state) glBindTexture (GL_TEXTURE_2D, state->tex); } -static gboolean +static void render_scene (APP_STATE_T * state) { update_model (state); redraw_scene (state); TRACE_VC_MEMORY_ONCE_FOR_ID ("after render_scene", gid2); - return !state->sync_animation_with_video; + return; } static void @@ -964,9 +966,7 @@ update_image (APP_STATE_T * state, GstBuffer * buffer) TRACE_VC_MEMORY_ONCE_FOR_ID ("after glEGLImageTargetTexture2DOES", gid1); - if (state->sync_animation_with_video) { - render_scene (state); - } + render_scene (state); } static void @@ -978,6 +978,23 @@ init_intercom (APP_STATE_T * state) state->cond = g_cond_new (); } +static void +terminate_intercom (APP_STATE_T * state) +{ + /* Release intercom */ + if (state->queue) { + g_async_queue_unref (state->queue); + } + + if (state->lock) { + g_mutex_free (state->lock); + } + + if (state->cond) { + g_cond_free (state->cond); + } +} + static void flush_internal (APP_STATE_T * state) { @@ -1159,12 +1176,6 @@ queue_object (APP_STATE_T * state, GstMiniObject * obj, gboolean synchronous) g_async_queue_push (state->queue, obj); - - if (state->sync_animation_with_video) { - g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc) handle_queued_objects, - state, NULL); - } - if (synchronous) { /* Waiting for object to be handled */ do { @@ -1176,13 +1187,6 @@ queue_object (APP_STATE_T * state, GstMiniObject * obj, gboolean synchronous) return TRUE; } -static gboolean -handle_msgs_and_render_scene (APP_STATE_T * state) -{ - handle_queued_objects (state); - return render_scene (state); -} - static void preroll_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad, gpointer user_data) @@ -1509,18 +1513,6 @@ handle_keyboard (GIOChannel * source, GIOCondition cond, APP_STATE_T * state) flush_start (state); gst_element_set_state (state->pipeline, GST_STATE_READY); break; - case 'S': - if (state->sync_animation_with_video) { - state->sync_animation_with_video = FALSE; - /* Add the rendering task */ - g_idle_add_full (G_PRIORITY_HIGH_IDLE, - (GSourceFunc) handle_msgs_and_render_scene, state, NULL); - g_print ("\nanimation is not synchoronized with video\n"); - } else { - state->sync_animation_with_video = TRUE; - g_print ("\nanimation is synchoronized with video\n"); - } - break; } } g_free (str); @@ -1617,6 +1609,47 @@ close_ogl (void) //============================================================================== +static void +open_ogl (void) +{ + TRACE_VC_MEMORY ("state 0"); + +#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_EGL) + bcm_host_init (); + TRACE_VC_MEMORY ("after bcm_host_init"); +#endif + + /* Start OpenGLES */ + init_ogl (state); + TRACE_VC_MEMORY ("after init_ogl"); + + /* Wrap the EGL display */ + state->gst_display = gst_egl_display_new (state->display, NULL); + + /* Setup the model world */ + init_model_proj (state); + TRACE_VC_MEMORY ("after init_model_proj"); + + /* initialize the OGLES texture(s) */ + init_textures (state); + TRACE_VC_MEMORY ("after init_textures"); +} + +static gpointer +render_func (gpointer data) +{ + open_ogl (); + state->running = TRUE; + + do { + handle_queued_objects (state); + g_usleep (0); + } while (state->running == TRUE); + + close_ogl (); + return NULL; +} + int main (int argc, char **argv) { @@ -1628,11 +1661,11 @@ main (int argc, char **argv) GOptionEntry options[] = { {NULL} }; + GThread *rthread; /* Clear application state */ memset (state, 0, sizeof (*state)); state->animate = TRUE; - state->sync_animation_with_video = TRUE; /* must initialise the threading system before using any other GLib funtion */ if (!g_thread_supported ()) @@ -1655,31 +1688,16 @@ main (int argc, char **argv) /* Initialize GStreamer */ gst_init (&argc, &argv); - TRACE_VC_MEMORY ("state 0"); - -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_EGL) - bcm_host_init (); - TRACE_VC_MEMORY ("after bcm_host_init"); -#endif - - /* Start OpenGLES */ - init_ogl (state); - TRACE_VC_MEMORY ("after init_ogl"); - - /* Wrap the EGL display */ - state->gst_display = gst_egl_display_new (state->display, NULL); - - /* Setup the model world */ - init_model_proj (state); - TRACE_VC_MEMORY ("after init_model_proj"); - - /* initialize the OGLES texture(s) */ - init_textures (state); - TRACE_VC_MEMORY ("after init_textures"); - /* initialize inter thread comunnication */ init_intercom (state); + TRACE_VC_MEMORY ("state 0"); + + if (!(rthread = g_thread_new ("render", (GThreadFunc) render_func, NULL))) { + g_print ("Render thread create failed\n"); + exit (1); + } + /* Initialize player */ if (gst_uri_is_valid (argv[1])) { res = init_playbin_player (state, argv[1]); @@ -1706,16 +1724,9 @@ main (int argc, char **argv) " l - Query position/duration\n" " f - Seek 30 seconds forward \n" " b - Seek 30 seconds backward \n" - " S - Toggle synchronization of video and animation \n" " q - Quit \n"); /* *INDENT-ON* */ - if (!state->sync_animation_with_video) { - /* Add the rendering task */ - g_idle_add_full (G_PRIORITY_HIGH_IDLE, - (GSourceFunc) handle_msgs_and_render_scene, state, NULL); - } - /* Connect the bus handlers */ bus = gst_element_get_bus (state->pipeline); @@ -1748,25 +1759,16 @@ done: gst_object_unref (state->pipeline); } - /* Release intercom */ - if (state->queue) { - g_async_queue_unref (state->queue); - } - - if (state->lock) { - g_mutex_free (state->lock); - } - - if (state->cond) { - g_cond_free (state->cond); - } - /* Unref the mainloop */ if (state->main_loop) { g_main_loop_unref (state->main_loop); } - close_ogl (); + /* Stop rendering thread */ + state->running = FALSE; + g_thread_join (rthread); + + terminate_intercom (state); TRACE_VC_MEMORY ("at exit"); return 0; -- cgit v1.2.3