[vlc-devel] [PATCH 01/16] core: add viewpoint to change the yaw/pitch/roll view during playback

Thomas Guillem thomas at gllm.fr
Wed Nov 9 18:32:55 CET 2016


From: Steve Lhomme <robux4 at videolabs.io>

These changes allow for us to change the viewpoint for a given vout, which is
the foundation required in order to play, and navigate, the contents of 360
videos.

Three new arguments has been added so that a user can decide where to start
playing within the 360 globe.

Signed-off-by: Thomas Guillem <thomas at gllm.fr>
---
 include/vlc_common.h             |  1 +
 include/vlc_vout.h               | 12 ++++++++
 include/vlc_vout_display.h       |  7 +++++
 include/vlc_vout_wrapper.h       |  3 ++
 src/libvlc-module.c              | 25 ++++++++++++++++
 src/libvlccore.sym               |  2 ++
 src/playlist/engine.c            | 11 +++++++
 src/playlist/playlist_internal.h |  3 ++
 src/video_output/control.h       |  5 ++++
 src/video_output/display.c       | 63 +++++++++++++++++++++++++++++++++++++++-
 src/video_output/video_output.c  | 29 ++++++++++++++++++
 src/video_output/vout_intf.c     | 16 ++++++++++
 12 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/include/vlc_common.h b/include/vlc_common.h
index a9683d6..0b1db73 100644
--- a/include/vlc_common.h
+++ b/include/vlc_common.h
@@ -249,6 +249,7 @@ typedef audio_format_t audio_sample_format_t;
 
 /* Video */
 typedef struct vout_thread_t vout_thread_t;
+typedef struct vlc_viewpoint_t vlc_viewpoint_t;
 
 typedef video_format_t video_frame_format_t;
 typedef struct picture_t picture_t;
diff --git a/include/vlc_vout.h b/include/vlc_vout.h
index 600cb56..cc53079 100644
--- a/include/vlc_vout.h
+++ b/include/vlc_vout.h
@@ -82,6 +82,13 @@ struct vout_thread_t {
 #define VOUT_ALIGN_BOTTOM       0x0008
 #define VOUT_ALIGN_VMASK        0x000C
 
+#define VLC_VIEWPOINT_RADIAN_UNIT 10000
+struct vlc_viewpoint_t {
+    int32_t yaw;   /* yaw in radians * 10,000 */
+    int32_t pitch; /* pitch in radians * 10,000 */
+    int32_t roll;  /* roll in radians * 10,000 */
+};
+
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
@@ -156,6 +163,11 @@ VLC_API void vout_FlushSubpictureChannel( vout_thread_t *, int );
 
 VLC_API void vout_EnableFilter( vout_thread_t *, const char *,bool , bool  );
 
+VLC_API void vout_GetViewpoint( vout_thread_t *, vlc_viewpoint_t *p_viewpoint );
+VLC_API void vout_UpdateViewpoint( vout_thread_t *,
+                                   const vlc_viewpoint_t *p_viewpoint,
+                                   bool absolute);
+
 /**@}*/
 
 #endif /* _VLC_VIDEO_H */
diff --git a/include/vlc_vout_display.h b/include/vlc_vout_display.h
index 817f770..e1efe00 100644
--- a/include/vlc_vout_display.h
+++ b/include/vlc_vout_display.h
@@ -30,6 +30,7 @@
 #include <vlc_subpicture.h>
 #include <vlc_keys.h>
 #include <vlc_mouse.h>
+#include <vlc_vout.h>
 #include <vlc_vout_window.h>
 
 /**
@@ -115,6 +116,8 @@ typedef struct {
         int den;
     } zoom;
 
+    vlc_viewpoint_t viewpoint;
+
 } vout_display_cfg_t;
 
 /**
@@ -175,6 +178,10 @@ enum {
      * The cropping requested is stored by video_format_t::i_x/y_offset and
      * video_format_t::i_visible_width/height */
     VOUT_DISPLAY_CHANGE_SOURCE_CROP,   /* const video_format_t *p_source */
+
+    /* Ask the module to acknowledge/refuse VR/360° viewing direction after
+     * being requested externally */
+    VOUT_DISPLAY_CHANGE_VIEWPOINT,   /* const vout_display_cfg_t *p_cfg */
 };
 
 /**
diff --git a/include/vlc_vout_wrapper.h b/include/vlc_vout_wrapper.h
index 419bfc8..bf6506a 100644
--- a/include/vlc_vout_wrapper.h
+++ b/include/vlc_vout_wrapper.h
@@ -93,6 +93,9 @@ void vout_SetDisplayZoom(vout_display_t *, unsigned num, unsigned den);
 void vout_SetDisplayAspect(vout_display_t *, unsigned num, unsigned den);
 void vout_SetDisplayCrop(vout_display_t *, unsigned num, unsigned den,
                          unsigned left, unsigned top, int right, int bottom);
+void vout_GetDisplayViewpoint(vout_display_t *, vlc_viewpoint_t *p_viewpoint);
+void vout_UpdateDisplayViewpoint(vout_display_t *, const vlc_viewpoint_t *,
+                                 bool absolute);
 
 #endif /* VLC_VOUT_WRAPPER_H */
 
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 035bcd2..05b171d 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -433,6 +433,22 @@ static const char *const ppsz_pos_descriptions[] =
     "aspect, or a float value (1.25, 1.3333, etc.) expressing pixel " \
     "squareness.")
 
+#define VIEWPOINT_YAW_TEXT N_("Viewpoint Yaw")
+#define VIEWPOINT_YAW_LONGTEXT N_( \
+    "This forces the user viewpoint yaw (horizontal shift) for the displayed " \
+    "video, in radians." )
+
+#define VIEWPOINT_PITCH_TEXT N_("Viewpoint Pitch")
+#define VIEWPOINT_PITCH_LONGTEXT N_( \
+    "This forces the user viewpoint pitch (vertical shift) for the displayed " \
+    "video, in radians." )
+
+#define VIEWPOINT_ROLL_TEXT N_("Viewpoint Roll")
+#define VIEWPOINT_ROLL_LONGTEXT N_( \
+    "This forces the user viewpoint roll (head tilting) for the displayed " \
+    "video, in radians." )
+
+
 #define AUTOSCALE_TEXT N_("Video Auto Scaling")
 #define AUTOSCALE_LONGTEXT N_( \
     "Let the video scale to fit a given window or fullscreen.")
@@ -1589,6 +1605,15 @@ vlc_module_begin ()
     add_string( "aspect-ratio", NULL,
                 ASPECT_RATIO_TEXT, ASPECT_RATIO_LONGTEXT, false )
         change_safe ()
+    add_float( "viewpoint-yaw", 0.,
+                VIEWPOINT_YAW_TEXT, VIEWPOINT_YAW_LONGTEXT, false )
+        change_safe ()
+    add_float( "viewpoint-pitch", 0.,
+                VIEWPOINT_PITCH_TEXT, VIEWPOINT_PITCH_LONGTEXT, false )
+        change_safe ()
+    add_float( "viewpoint-roll", 0.,
+                VIEWPOINT_ROLL_TEXT, VIEWPOINT_ROLL_LONGTEXT, false )
+        change_safe ()
     add_bool( "autoscale", true, AUTOSCALE_TEXT, AUTOSCALE_LONGTEXT, false )
         change_safe ()
     add_obsolete_float( "scale" ) /* since 3.0.0 */
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 8bb2dac..c110b66 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -734,6 +734,8 @@ vout_window_Delete
 vout_display_GetDefaultDisplaySize
 vout_display_PlacePicture
 vout_display_SendMouseMovedDisplayCoordinates
+vout_GetViewpoint
+vout_UpdateViewpoint
 xml_Create
 text_style_Copy
 text_style_Create
diff --git a/src/playlist/engine.c b/src/playlist/engine.c
index 7c00a48..e179a69 100644
--- a/src/playlist/engine.c
+++ b/src/playlist/engine.c
@@ -479,6 +479,17 @@ static void VariablesInit( playlist_t *p_playlist )
     var_Create( p_playlist, "mute", VLC_VAR_BOOL );
     var_Create( p_playlist, "volume", VLC_VAR_FLOAT );
     var_SetFloat( p_playlist, "volume", -1.f );
+
+    vlc_viewpoint_t *p_vp = &pl_priv(p_playlist)->viewpoint;
+    p_vp->yaw   = var_InheritFloat( p_playlist, "viewpoint-yaw" )
+                * VLC_VIEWPOINT_RADIAN_UNIT;
+    p_vp->pitch = var_InheritFloat( p_playlist, "viewpoint-pitch" )
+                * VLC_VIEWPOINT_RADIAN_UNIT;
+    p_vp->roll  = var_InheritFloat( p_playlist, "viewpoint-roll" )
+                * VLC_VIEWPOINT_RADIAN_UNIT;
+
+    var_Create( p_playlist, "viewpoint", VLC_VAR_ADDRESS );
+    var_SetAddress( p_playlist, "viewpoint", p_vp );
 }
 
 playlist_item_t * playlist_CurrentPlayingItem( playlist_t * p_playlist )
diff --git a/src/playlist/playlist_internal.h b/src/playlist/playlist_internal.h
index d655dc3..faa7a14 100644
--- a/src/playlist/playlist_internal.h
+++ b/src/playlist/playlist_internal.h
@@ -35,6 +35,7 @@
  */
 
 #include "input/input_interface.h"
+#include "vlc_vout.h"
 #include <assert.h>
 
 #include "art.h"
@@ -87,6 +88,8 @@ typedef struct playlist_private_t
 
     bool     b_tree; /**< Display as a tree */
     bool     b_preparse; /**< Preparse items */
+
+    vlc_viewpoint_t  viewpoint; /**< playback viewpoint */
 } playlist_private_t;
 
 #define pl_priv( pl ) ((playlist_private_t *)(pl))
diff --git a/src/video_output/control.h b/src/video_output/control.h
index eff9aa1..7aed1c5 100644
--- a/src/video_output/control.h
+++ b/src/video_output/control.h
@@ -58,6 +58,7 @@ enum {
     VOUT_CONTROL_CROP_BORDER,           /* border */
     VOUT_CONTROL_CROP_RATIO,            /* pair */
     VOUT_CONTROL_CROP_WINDOW,           /* window */
+    VOUT_CONTROL_VIEWPOINT,             /* viewpoint */
 };
 
 typedef struct {
@@ -93,6 +94,10 @@ typedef struct {
             unsigned width;
             unsigned height;
         } window;
+        struct {
+            bool absolute;
+            vlc_viewpoint_t viewpoint;
+        } vr_nav;
         const vout_configuration_t *cfg;
         subpicture_t *subpicture;
     } u;
diff --git a/src/video_output/display.c b/src/video_output/display.c
index ecf661a..ee3ac0a 100644
--- a/src/video_output/display.c
+++ b/src/video_output/display.c
@@ -373,6 +373,10 @@ struct vout_display_owner_sys_t {
         unsigned den;
     } crop;
 
+    bool ch_viewpoint;
+    vlc_viewpoint_t viewpoint;
+    vlc_mutex_t viewpoint_lock;
+
     /* */
     video_format_t source;
     filter_chain_t *filters;
@@ -850,7 +854,8 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
             !ch_wm_state &&
 #endif
             !osys->ch_sar &&
-            !osys->ch_crop) {
+            !osys->ch_crop &&
+            !osys->ch_viewpoint) {
 
             if (!osys->cfg.is_fullscreen && osys->fit_window != 0) {
                 VoutDisplayFitWindow(vd, osys->fit_window == -1);
@@ -1034,6 +1039,20 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
             osys->crop.den    = crop_den;
             osys->ch_crop = false;
         }
+        if (osys->ch_viewpoint) {
+            vout_display_cfg_t cfg = osys->cfg;
+
+            vlc_mutex_lock(&osys->viewpoint_lock);
+            cfg.viewpoint = osys->viewpoint;
+
+            if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_VIEWPOINT, &cfg)) {
+                msg_Err(vd, "Failed to change Viewpoint");
+                osys->viewpoint = osys->cfg.viewpoint;
+            }
+            osys->cfg.viewpoint = osys->viewpoint;
+            osys->ch_viewpoint  = false;
+            vlc_mutex_unlock(&osys->viewpoint_lock);
+        }
 
         /* */
         if (reset_pictures) {
@@ -1193,6 +1212,44 @@ void vout_SetDisplayCrop(vout_display_t *vd,
     }
 }
 
+void vout_GetDisplayViewpoint(vout_display_t *vd, vlc_viewpoint_t *p_viewpoint)
+{
+    vout_display_owner_sys_t *osys = vd->owner.sys;
+
+    vlc_mutex_lock(&osys->viewpoint_lock);
+    *p_viewpoint = osys->viewpoint;
+    vlc_mutex_unlock(&osys->viewpoint_lock);
+}
+
+void vout_UpdateDisplayViewpoint(vout_display_t *vd,
+                                 const vlc_viewpoint_t *p_viewpoint,
+                                 bool absolute)
+{
+    vout_display_owner_sys_t *osys = vd->owner.sys;
+
+    vlc_mutex_lock(&osys->viewpoint_lock);
+    if (absolute) {
+        if (osys->viewpoint.yaw   != p_viewpoint->yaw ||
+            osys->viewpoint.pitch != p_viewpoint->pitch ||
+            osys->viewpoint.roll  != p_viewpoint->roll) {
+            osys->viewpoint = *p_viewpoint;
+
+            osys->ch_viewpoint = true;
+        }
+    } else {
+        if (0 != p_viewpoint->yaw ||
+            0 != p_viewpoint->pitch ||
+            0 != p_viewpoint->roll) {
+            osys->viewpoint.yaw   += p_viewpoint->yaw;
+            osys->viewpoint.pitch += p_viewpoint->pitch;
+            osys->viewpoint.roll  += p_viewpoint->roll;
+
+            osys->ch_viewpoint = true;
+        }
+    }
+    vlc_mutex_unlock(&osys->viewpoint_lock);
+}
+
 static vout_display_t *DisplayNew(vout_thread_t *vout,
                                   const video_format_t *source,
                                   const vout_display_state_t *state,
@@ -1218,6 +1275,8 @@ static vout_display_t *DisplayNew(vout_thread_t *vout,
 
     vlc_mutex_init(&osys->lock);
 
+    vlc_mutex_init(&osys->viewpoint_lock);
+
     vlc_mouse_Init(&osys->mouse.state);
     osys->mouse.last_moved = mdate();
     osys->mouse.double_click_timeout = double_click_timeout;
@@ -1289,6 +1348,7 @@ static vout_display_t *DisplayNew(vout_thread_t *vout,
 
     return p_display;
 error:
+    vlc_mutex_destroy(&osys->viewpoint_lock);
     vlc_mutex_destroy(&osys->lock);
     free(osys);
     return NULL;
@@ -1317,6 +1377,7 @@ void vout_DeleteDisplay(vout_display_t *vd, vout_display_state_t *state)
         vlc_join(osys->event.thread, NULL);
         block_FifoRelease(osys->event.fifo);
     }
+    vlc_mutex_destroy(&osys->viewpoint_lock);
     vlc_mutex_destroy(&osys->lock);
     free(osys);
 }
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 7994bec..1a9369d 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -540,12 +540,31 @@ void vout_ControlChangeSubMargin(vout_thread_t *vout, int margin)
                              margin);
 }
 
+void vout_GetViewpoint( vout_thread_t *vout, vlc_viewpoint_t *p_viewpoint )
+{
+    vout_GetDisplayViewpoint(vout->p->display.vd, p_viewpoint);
+}
+
+void vout_UpdateViewpoint( vout_thread_t *vout,
+                           const vlc_viewpoint_t *p_viewpoint, bool absolute )
+{
+    vout_control_cmd_t cmd;
+    vout_control_cmd_Init(&cmd, VOUT_CONTROL_VIEWPOINT);
+    cmd.u.vr_nav.viewpoint = *p_viewpoint;
+    cmd.u.vr_nav.absolute = absolute;
+
+    vout_control_Push(&vout->p->control, &cmd);
+}
+
 /* */
 static void VoutGetDisplayCfg(vout_thread_t *vout, vout_display_cfg_t *cfg, const char *title)
 {
     /* Load configuration */
     cfg->is_fullscreen = var_CreateGetBool(vout, "fullscreen")
                          || var_InheritBool(vout, "video-wallpaper");
+    cfg->viewpoint.yaw   = 0.0f;
+    cfg->viewpoint.pitch = 0.0f;
+    cfg->viewpoint.roll  = 0.0f;
     cfg->display.title = title;
     const int display_width = var_CreateGetInteger(vout, "width");
     const int display_height = var_CreateGetInteger(vout, "height");
@@ -1289,6 +1308,13 @@ static void ThreadExecuteCropRatio(vout_thread_t *vout,
                         0, 0, 0, 0);
 }
 
+static void ThreadExecuteViewpoint(vout_thread_t *vout,
+                                   const vlc_viewpoint_t *p_viewpoint,
+                                   bool absolute)
+{
+    vout_UpdateDisplayViewpoint(vout->p->display.vd, p_viewpoint, absolute);
+}
+
 static int ThreadStart(vout_thread_t *vout, vout_display_state_t *state)
 {
     vlc_mouse_Init(&vout->p->mouse);
@@ -1548,6 +1574,9 @@ static int ThreadControl(vout_thread_t *vout, vout_control_cmd_t cmd)
                 cmd.u.border.left,  cmd.u.border.top,
                 cmd.u.border.right, cmd.u.border.bottom);
         break;
+    case VOUT_CONTROL_VIEWPOINT:
+        ThreadExecuteViewpoint(vout, &cmd.u.vr_nav.viewpoint, cmd.u.vr_nav.absolute);
+        break;
     default:
         break;
     }
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index 11240c8..5b90447 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -57,6 +57,8 @@ static int AutoScaleCallback( vlc_object_t *, char const *,
                               vlc_value_t, vlc_value_t, void * );
 static int ZoomCallback( vlc_object_t *, char const *,
                          vlc_value_t, vlc_value_t, void * );
+static int ViewpointCallback( vlc_object_t *, char const *,
+                              vlc_value_t, vlc_value_t, void * );
 static int AboveCallback( vlc_object_t *, char const *,
                           vlc_value_t, vlc_value_t, void * );
 static int WallPaperCallback( vlc_object_t *, char const *,
@@ -252,6 +254,10 @@ void vout_IntfInit( vout_thread_t *p_vout )
     var_Change( p_vout, "video-on-top", VLC_VAR_SETTEXT, &text, NULL );
     var_AddCallback( p_vout, "video-on-top", AboveCallback, NULL );
 
+    /* Add a variable to indicate if the viewpoint to use to display the video */
+    var_Create( p_vout, "viewpoint", VLC_VAR_ADDRESS | VLC_VAR_DOINHERIT );
+    var_AddCallback( p_vout, "viewpoint", ViewpointCallback, NULL );
+
     /* Add a variable to indicate if the window should be below all others */
     var_Create( p_vout, "video-wallpaper", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
     var_AddCallback( p_vout, "video-wallpaper", WallPaperCallback,
@@ -309,6 +315,7 @@ void vout_IntfReinit( vout_thread_t *p_vout )
     var_TriggerCallback( p_vout, "zoom" );
     var_TriggerCallback( p_vout, "crop" );
     var_TriggerCallback( p_vout, "aspect-ratio" );
+    var_TriggerCallback( p_vout, "viewpoint" );
 
     var_TriggerCallback( p_vout, "video-on-top" );
     var_TriggerCallback( p_vout, "video-wallpaper" );
@@ -602,6 +609,15 @@ static int ZoomCallback( vlc_object_t *obj, char const *name,
     return VLC_SUCCESS;
 }
 
+static int ViewpointCallback(vlc_object_t *obj, char const *cmd,
+                             vlc_value_t oldval, vlc_value_t newval, void *data)
+{
+    vout_UpdateViewpoint((vout_thread_t *)obj, newval.p_address, true);
+
+    VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
+    return VLC_SUCCESS;
+}
+
 static int AboveCallback( vlc_object_t *obj, char const *name,
                           vlc_value_t prev, vlc_value_t cur, void *data )
 {
-- 
2.9.3



More information about the vlc-devel mailing list