mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-03 15:06:34 +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_width;
|
||||||
uint32_t screen_height;
|
uint32_t screen_height;
|
||||||
gboolean animate;
|
gboolean animate;
|
||||||
gboolean sync_animation_with_video;
|
|
||||||
|
|
||||||
/* OpenGL|ES objects */
|
/* OpenGL|ES objects */
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
|
@ -179,6 +178,9 @@ typedef struct
|
||||||
GstBuffer *last_buffer;
|
GstBuffer *last_buffer;
|
||||||
|
|
||||||
GstCaps *current_caps;
|
GstCaps *current_caps;
|
||||||
|
|
||||||
|
/* Rendering thread state */
|
||||||
|
gboolean running;
|
||||||
} APP_STATE_T;
|
} APP_STATE_T;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -933,14 +935,14 @@ init_textures (APP_STATE_T * state)
|
||||||
glBindTexture (GL_TEXTURE_2D, state->tex);
|
glBindTexture (GL_TEXTURE_2D, state->tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
render_scene (APP_STATE_T * state)
|
render_scene (APP_STATE_T * state)
|
||||||
{
|
{
|
||||||
update_model (state);
|
update_model (state);
|
||||||
redraw_scene (state);
|
redraw_scene (state);
|
||||||
TRACE_VC_MEMORY_ONCE_FOR_ID ("after render_scene", gid2);
|
TRACE_VC_MEMORY_ONCE_FOR_ID ("after render_scene", gid2);
|
||||||
|
|
||||||
return !state->sync_animation_with_video;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -964,10 +966,8 @@ update_image (APP_STATE_T * state, GstBuffer * buffer)
|
||||||
|
|
||||||
TRACE_VC_MEMORY_ONCE_FOR_ID ("after glEGLImageTargetTexture2DOES", gid1);
|
TRACE_VC_MEMORY_ONCE_FOR_ID ("after glEGLImageTargetTexture2DOES", gid1);
|
||||||
|
|
||||||
if (state->sync_animation_with_video) {
|
|
||||||
render_scene (state);
|
render_scene (state);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_intercom (APP_STATE_T * state)
|
init_intercom (APP_STATE_T * state)
|
||||||
|
@ -978,6 +978,23 @@ init_intercom (APP_STATE_T * state)
|
||||||
state->cond = g_cond_new ();
|
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
|
static void
|
||||||
flush_internal (APP_STATE_T * state)
|
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);
|
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) {
|
if (synchronous) {
|
||||||
/* Waiting for object to be handled */
|
/* Waiting for object to be handled */
|
||||||
do {
|
do {
|
||||||
|
@ -1176,13 +1187,6 @@ queue_object (APP_STATE_T * state, GstMiniObject * obj, gboolean synchronous)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
handle_msgs_and_render_scene (APP_STATE_T * state)
|
|
||||||
{
|
|
||||||
handle_queued_objects (state);
|
|
||||||
return render_scene (state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
preroll_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
|
preroll_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
|
@ -1509,18 +1513,6 @@ handle_keyboard (GIOChannel * source, GIOCondition cond, APP_STATE_T * state)
|
||||||
flush_start (state);
|
flush_start (state);
|
||||||
gst_element_set_state (state->pipeline, GST_STATE_READY);
|
gst_element_set_state (state->pipeline, GST_STATE_READY);
|
||||||
break;
|
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);
|
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
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -1628,11 +1661,11 @@ main (int argc, char **argv)
|
||||||
GOptionEntry options[] = {
|
GOptionEntry options[] = {
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
GThread *rthread;
|
||||||
|
|
||||||
/* Clear application state */
|
/* Clear application state */
|
||||||
memset (state, 0, sizeof (*state));
|
memset (state, 0, sizeof (*state));
|
||||||
state->animate = TRUE;
|
state->animate = TRUE;
|
||||||
state->sync_animation_with_video = TRUE;
|
|
||||||
|
|
||||||
/* must initialise the threading system before using any other GLib funtion */
|
/* must initialise the threading system before using any other GLib funtion */
|
||||||
if (!g_thread_supported ())
|
if (!g_thread_supported ())
|
||||||
|
@ -1655,31 +1688,16 @@ main (int argc, char **argv)
|
||||||
/* Initialize GStreamer */
|
/* Initialize GStreamer */
|
||||||
gst_init (&argc, &argv);
|
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 */
|
/* initialize inter thread comunnication */
|
||||||
init_intercom (state);
|
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 */
|
/* Initialize player */
|
||||||
if (gst_uri_is_valid (argv[1])) {
|
if (gst_uri_is_valid (argv[1])) {
|
||||||
res = init_playbin_player (state, argv[1]);
|
res = init_playbin_player (state, argv[1]);
|
||||||
|
@ -1706,16 +1724,9 @@ main (int argc, char **argv)
|
||||||
" l - Query position/duration\n"
|
" l - Query position/duration\n"
|
||||||
" f - Seek 30 seconds forward \n"
|
" f - Seek 30 seconds forward \n"
|
||||||
" b - Seek 30 seconds backward \n"
|
" b - Seek 30 seconds backward \n"
|
||||||
" S - Toggle synchronization of video and animation \n"
|
|
||||||
" q - Quit \n");
|
" q - Quit \n");
|
||||||
/* *INDENT-ON* */
|
/* *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 */
|
/* Connect the bus handlers */
|
||||||
bus = gst_element_get_bus (state->pipeline);
|
bus = gst_element_get_bus (state->pipeline);
|
||||||
|
|
||||||
|
@ -1748,25 +1759,16 @@ done:
|
||||||
gst_object_unref (state->pipeline);
|
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 */
|
/* Unref the mainloop */
|
||||||
if (state->main_loop) {
|
if (state->main_loop) {
|
||||||
g_main_loop_unref (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");
|
TRACE_VC_MEMORY ("at exit");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue