summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosep Torra <n770galaxy@gmail.com>2013-09-20 09:34:37 +0200
committerJosep Torra <n770galaxy@gmail.com>2013-09-20 18:17:34 +0200
commite6633182f3305804de97cf8ec5e00c097d4e4a79 (patch)
tree50662fbf15b2da4db715133e95a5a5a8d711ffe1
parent78dc6235d43066e56566b87e8dc7178e86a5b7f5 (diff)
examples: use dedicated thread for rendering the scene
Produces smother animation and prevents dropping frames due busy mainloop.
-rw-r--r--examples/egl/testegl.c152
1 files 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
@@ -979,6 +979,23 @@ init_intercom (APP_STATE_T * state)
}
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)
{
if (state->current_mem) {
@@ -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;