[vlc-devel] [PATCH 06/10] vrnav: add control to change the viewpoint in 360° videos with the mouse
Steve Lhomme
robux4 at videolabs.io
Fri Sep 16 18:00:32 CEST 2016
--
replaces https://patches.videolan.org/patch/14424/ using only the "viewpoint" variable
---
modules/control/Makefile.am | 4 +-
modules/control/vrnav.c | 229 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 232 insertions(+), 1 deletion(-)
create mode 100644 modules/control/vrnav.c
diff --git a/modules/control/Makefile.am b/modules/control/Makefile.am
index 2469a86..dfb38c0 100644
--- a/modules/control/Makefile.am
+++ b/modules/control/Makefile.am
@@ -8,13 +8,15 @@ libnetsync_plugin_la_SOURCES = control/netsync.c
libnetsync_plugin_la_LIBADD = $(SOCKET_LIBS)
liboldrc_plugin_la_SOURCES = control/oldrc.c control/intromsg.h
liboldrc_plugin_la_LIBADD = $(SOCKET_LIBS) $(LIBM)
+libvrnav_plugin_la_SOURCES = control/vrnav.c
control_LTLIBRARIES = \
libdummy_plugin.la \
libgestures_plugin.la \
libhotkeys_plugin.la \
libnetsync_plugin.la \
- liboldrc_plugin.la
+ liboldrc_plugin.la \
+ libvrnav_plugin.la
liblirc_plugin_la_SOURCES = control/lirc.c
liblirc_plugin_la_LIBADD = -llirc_client
diff --git a/modules/control/vrnav.c b/modules/control/vrnav.c
new file mode 100644
index 0000000..de0e2fd
--- /dev/null
+++ b/modules/control/vrnav.c
@@ -0,0 +1,229 @@
+ /*
+ * VR/360 navigation hooks.
+ *
+ * Copyright (C) 2016 the VideoLAN team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation Inc. 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <math.h>
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_interface.h>
+#include <vlc_input.h>
+#include <vlc_keys.h>
+#include <vlc_playlist.h>
+#include <vlc_vout.h>
+
+/*****************************************************************************
+ * intf_sys_t: description and status of interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ vlc_mutex_t lock;
+ input_thread_t *p_input;
+ vout_thread_t *p_vout;
+ bool b_button_pressed;
+ int i_last_x, i_last_y;
+ float f_last_yaw, f_last_pitch, f_last_roll;
+ unsigned int i_pattern;
+};
+
+
+static int MovedEvent( vlc_object_t *p_this, char const *psz_var,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_data;
+ intf_sys_t *p_sys = p_intf->p_sys;
+
+ (void) p_this; (void) psz_var; (void) oldval;
+
+ vlc_mutex_lock( &p_sys->lock );
+ if( p_sys->b_button_pressed )
+ {
+ char buf[3 * 13];
+ int i_horizontal = newval.coords.x - p_sys->i_last_x;
+ int i_vertical = newval.coords.y - p_sys->i_last_y;
+
+ float yaw = p_sys->f_last_yaw + (float)i_horizontal / 200;
+ float pitch = p_sys->f_last_pitch + (float)i_vertical / 200;
+
+ snprintf(buf, sizeof (buf), "%.7f:%.7f:%.7f", yaw, pitch, p_sys->f_last_roll);
+ var_SetString( p_sys->p_vout, "viewpoint", buf);
+ msg_Dbg(p_intf, "new viewpoint %s", buf);
+
+ }
+ vlc_mutex_unlock( &p_sys->lock );
+
+ return VLC_SUCCESS;
+}
+
+static int ButtonEvent( vlc_object_t *p_this, char const *psz_var,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ intf_thread_t *p_intf = p_data;
+ intf_sys_t *p_sys = p_intf->p_sys;
+
+ (void) psz_var; (void) oldval;
+
+ vlc_mutex_lock( &p_sys->lock );
+ if( newval.i_int & 0x01)
+ {
+ if( !p_sys->b_button_pressed )
+ {
+ p_sys->b_button_pressed = true;
+ char *psz_vp = var_GetNonEmptyString(p_sys->p_vout, "viewpoint");
+ if (psz_vp == NULL || sscanf( psz_vp, "%f:%f:%f",
+ &p_sys->f_last_yaw,
+ &p_sys->f_last_pitch,
+ &p_sys->f_last_roll) != 3)
+ p_sys->f_last_yaw = p_sys->f_last_pitch = p_sys->f_last_roll = 0.0f;
+ var_GetCoords( p_this, "mouse-moved",
+ &p_sys->i_last_x, &p_sys->i_last_y );
+ }
+ }
+ else
+ {
+ if( p_sys->b_button_pressed )
+ p_sys->b_button_pressed = false;
+ }
+ vlc_mutex_unlock( &p_sys->lock );
+
+ return VLC_SUCCESS;
+}
+
+static int InputEvent( vlc_object_t *p_this, char const *psz_var,
+ vlc_value_t oldval, vlc_value_t val, void *p_data )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+ intf_thread_t *p_intf = p_data;
+ intf_sys_t *p_sys = p_intf->p_sys;
+
+ (void) psz_var; (void) oldval;
+
+ switch( val.i_int )
+ {
+ case INPUT_EVENT_VOUT:
+ /* intf-event is serialized against itself and is the sole user of
+ * p_sys->p_vout. So there is no need to acquire the lock currently. */
+ if( p_sys->p_vout != NULL )
+ { /* /!\ Beware of lock inversion with var_DelCallback() /!\ */
+ var_DelCallback( p_sys->p_vout, "mouse-moved", MovedEvent,
+ p_intf );
+ var_DelCallback( p_sys->p_vout, "mouse-button-down", ButtonEvent,
+ p_intf );
+ vlc_object_release( p_sys->p_vout );
+ }
+
+ p_sys->p_vout = input_GetVout( p_input );
+ if( p_sys->p_vout != NULL )
+ {
+ var_AddCallback( p_sys->p_vout, "mouse-moved", MovedEvent,
+ p_intf );
+ var_AddCallback( p_sys->p_vout, "mouse-button-down", ButtonEvent,
+ p_intf );
+ }
+ break;
+ }
+ return VLC_SUCCESS;
+}
+
+static int PlaylistEvent( vlc_object_t *p_this, char const *psz_var,
+ vlc_value_t oldval, vlc_value_t val, void *p_data )
+{
+ intf_thread_t *p_intf = p_data;
+ intf_sys_t *p_sys = p_intf->p_sys;
+ input_thread_t *p_input = val.p_address;
+
+ (void) p_this; (void) psz_var;
+
+ if( p_sys->p_input != NULL )
+ {
+ assert( p_sys->p_input == oldval.p_address );
+ var_DelCallback( p_sys->p_input, "intf-event", InputEvent, p_intf );
+ }
+
+ p_sys->p_input = p_input;
+
+ if( p_input != NULL )
+ var_AddCallback( p_input, "intf-event", InputEvent, p_intf );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * OpenIntf: initialize interface
+ *****************************************************************************/
+static int Open ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ intf_sys_t *p_sys = p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( unlikely(p_sys == NULL) )
+ return VLC_ENOMEM;
+
+ // Configure the module
+ vlc_mutex_init( &p_sys->lock );
+ p_sys->p_input = NULL;
+ p_sys->p_vout = NULL;
+ p_sys->b_button_pressed = false;
+
+ var_AddCallback( pl_Get(p_intf), "input-current", PlaylistEvent, p_intf );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * CloseIntf: destroy dummy interface
+ *****************************************************************************/
+static void Close ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+ intf_sys_t *p_sys = p_intf->p_sys;
+
+ /* Destroy the callbacks (the order matters!) */
+ var_DelCallback( pl_Get(p_intf), "input-current", PlaylistEvent, p_intf );
+
+ if( p_sys->p_input != NULL )
+ var_DelCallback( p_sys->p_input, "intf-event", InputEvent, p_intf );
+
+ if( p_sys->p_vout )
+ {
+ var_DelCallback( p_sys->p_vout, "mouse-moved", MovedEvent, p_intf );
+ var_DelCallback( p_sys->p_vout, "mouse-button-down",
+ ButtonEvent, p_intf );
+ vlc_object_release( p_sys->p_vout );
+ }
+
+ /* Destroy structure */
+ vlc_mutex_destroy( &p_sys->lock );
+ free( p_sys );
+}
+
+vlc_module_begin ()
+ set_shortname( N_("vrnav"))
+ set_category( CAT_INTERFACE )
+ set_subcategory( SUBCAT_INTERFACE_CONTROL )
+ set_description( N_("VR/360° mouse navigation interface") )
+ set_capability( "interface", 0 )
+ set_callbacks( Open, Close )
+ add_shortcut( "vrnav" )
+vlc_module_end ()
More information about the vlc-devel
mailing list