mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 21:51:09 +00:00
examples: use dedicated thread for rendering the scene
Produces smother animation and prevents dropping frames due busy mainloop.
This commit is contained in:
parent
78dc6235d4
commit
e6633182f3
1 changed files with 77 additions and 75 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue