[vlc-devel] [PATCH 12/17] libvlc: add the API needed to set/get the viewpoint in 360° videos

Steve Lhomme robux4 at videolabs.io
Mon Nov 14 15:16:21 CET 2016


--
replaces https://patches.videolan.org/patch/14608/
* only use vout 0 in libvlc_video_get_viewpoint()
* libvlc_video_get_viewpoint() returns 0 on success

replaces https://patches.videolan.org/patch/14918/
* use a different CLI parameter for each viewpoint field
* removed extra line
* use retval

replaces https://patches.videolan.org/patch/14954/
* get_viewpoint can be used to keep the viewpoint between files
  but not more
* the API is not in float degrees
* the field of view now defaults to 80°
* no need to read the vout value, we are the unique source
---
 include/vlc/libvlc_media_player.h |  57 ++++++++++++++++++++-
 lib/libvlc.sym                    |   3 ++
 lib/media_player.c                |   8 +++
 lib/media_player_internal.h       |   2 +
 lib/video.c                       |  58 +++++++++++++++++++++
 test/Makefile.am                  |   2 +-
 test/libvlc/media_player.c        | 103 ++++++++++++++++++++++++++++++++++++++
 7 files changed, 231 insertions(+), 2 deletions(-)

diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 9a73b4f..596bb6d 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -603,7 +603,7 @@ LIBVLC_API int libvlc_media_player_set_evas_object( libvlc_media_player_t *p_mi,
  * or libvlc_audio_set_format_callbacks() as is the channels layout.
  *
  * Note that the number of samples is per channel. For instance, if the audio
- * track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds
+ * track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds
  * of audio signal - regardless of the number of audio channels. 
  *
  * \param data data pointer as passed to libvlc_audio_set_callbacks() [IN]
@@ -1167,6 +1167,61 @@ LIBVLC_API char *libvlc_video_get_aspect_ratio( libvlc_media_player_t *p_mi );
 LIBVLC_API void libvlc_video_set_aspect_ratio( libvlc_media_player_t *p_mi, const char *psz_aspect );
 
 /**
+ * Viewpoint for video outputs
+ *
+ * \warning allocate using libvlc_video_new_viewpoint()
+ */
+typedef struct libvlc_video_viewpoint_t
+{
+    float f_yaw;           /**< view point yaw in degrees */
+    float f_pitch;         /**< view point pitch in degrees */
+    float f_roll;          /**< view point roll in degrees */
+    float f_field_of_view; /** field of view in degrees (default 80.0f) */
+    float f_zoom;          /**< view point zoom factor (default 0.0f) */
+} libvlc_video_viewpoint_t;
+
+/**
+ * Create a video viewpoint structure.
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \return video viewpoint or NULL
+ *         (the result must be released with free() or libvlc_free()).
+ */
+LIBVLC_API libvlc_video_viewpoint_t *libvlc_video_new_viewpoint(void);
+
+/**
+ * Get current video viewpoint.
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \param p_mi the media player
+ * \param p_viewpoint video viewpoint allocated via libvlc_video_new_viewpoint()
+ *                    that will be filled with the vout value if it is found
+ *                    or the default value for the media player
+ * \retval -1 if an error was detected
+ * \retval 0 success
+ * \warning the call is synchronous and may not return the value used by the vout yet.
+ */
+LIBVLC_API int libvlc_video_get_viewpoint( libvlc_media_player_t *p_mi,
+                                           libvlc_video_viewpoint_t *p_viewpoint );
+
+/**
+ * Update the video viewpoint information by increasing/decreasing current values.
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \param p_mi the media player
+ * \param p_viewpoint video viewpoint offsets allocated via libvlc_video_new_viewpoint()
+ * \retval -1 if an error was detected
+ * \retval 0 success
+ *
+ * \note the values are set asynchronously, it will be used by the next frame displayed.
+ */
+LIBVLC_API int libvlc_video_set_viewpoint( libvlc_media_player_t *p_mi,
+                                           const libvlc_video_viewpoint_t *p_viewpoint );
+
+/**
  * Get current video subtitle.
  *
  * \param p_mi the media player
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index b994384..06868ff 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -283,6 +283,9 @@ libvlc_video_set_subtitle_file
 libvlc_video_set_teletext
 libvlc_video_set_track
 libvlc_video_take_snapshot
+libvlc_video_new_viewpoint
+libvlc_video_get_viewpoint
+libvlc_video_set_viewpoint
 libvlc_vlm_add_broadcast
 libvlc_vlm_add_vod
 libvlc_vlm_add_input
diff --git a/lib/media_player.c b/lib/media_player.c
index db08274..f392087 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -719,6 +719,14 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     if( aout != NULL )
         input_resource_PutAout(mp->input.p_resource, aout);
 
+    mp->viewpoint.yaw   = TO_MILLI_INT(var_InheritFloat(mp, "viewpoint-yaw"));
+    mp->viewpoint.pitch = TO_MILLI_INT(var_InheritFloat(mp, "viewpoint-pitch"));
+    mp->viewpoint.roll  = TO_MILLI_INT(var_InheritFloat(mp, "viewpoint-roll"));
+    mp->viewpoint.fov   = TO_MILLI_INT(var_InheritFloat(mp, "viewpoint-fov"));
+    mp->viewpoint.zoom  = TO_MILLI_INT(var_InheritFloat(mp, "viewpoint-zoom"));
+
+    var_Create (mp, "viewpoint", VLC_VAR_ADDRESS);
+    var_SetAddress( mp, "viewpoint", &mp->viewpoint );
     vlc_mutex_init (&mp->input.lock);
     mp->i_refcount = 1;
     mp->p_event_manager = libvlc_event_manager_new(mp);
diff --git a/lib/media_player_internal.h b/lib/media_player_internal.h
index f5f101b..1eca3c3 100644
--- a/lib/media_player_internal.h
+++ b/lib/media_player_internal.h
@@ -32,6 +32,7 @@
 #include <vlc/vlc.h>
 #include <vlc/libvlc_media.h>
 #include <vlc_input.h>
+#include <vlc_vout.h>
 
 #include "../modules/audio_filter/equalizer_presets.h"
 
@@ -53,6 +54,7 @@ struct libvlc_media_player_t
     libvlc_media_t * p_md; /* current media descriptor */
     libvlc_event_manager_t * p_event_manager;
     libvlc_state_t state;
+    vlc_viewpoint_t viewpoint;
 };
 
 /* Media player - audio, video */
diff --git a/lib/video.c b/lib/video.c
index 1046fba..95c95ff 100644
--- a/lib/video.c
+++ b/lib/video.c
@@ -282,6 +282,64 @@ void libvlc_video_set_aspect_ratio( libvlc_media_player_t *p_mi,
     free (pp_vouts);
 }
 
+libvlc_video_viewpoint_t *libvlc_video_new_viewpoint(void)
+{
+    return calloc(1, sizeof(libvlc_video_viewpoint_t));
+}
+
+int libvlc_video_get_viewpoint( libvlc_media_player_t *p_mi,
+                                libvlc_video_viewpoint_t *p_viewpoint )
+{
+    p_viewpoint->f_yaw           = FROM_MILLI_INT( p_mi->viewpoint.yaw );
+    p_viewpoint->f_pitch         = FROM_MILLI_INT( p_mi->viewpoint.pitch );
+    p_viewpoint->f_roll          = FROM_MILLI_INT( p_mi->viewpoint.roll );
+    p_viewpoint->f_field_of_view = FROM_MILLI_INT( p_mi->viewpoint.fov );
+    p_viewpoint->f_zoom          = FROM_MILLI_INT( p_mi->viewpoint.zoom );
+    return VLC_SUCCESS;
+}
+
+int libvlc_video_set_viewpoint( libvlc_media_player_t *p_mi,
+                                const libvlc_video_viewpoint_t *p_viewpoint )
+{
+    vlc_viewpoint_t update = {
+        .yaw   = TO_MILLI_INT( p_viewpoint->f_yaw ),
+        .pitch = TO_MILLI_INT( p_viewpoint->f_pitch ),
+        .roll  = TO_MILLI_INT( p_viewpoint->f_roll ),
+        .fov   = TO_MILLI_INT( p_viewpoint->f_field_of_view ),
+        .zoom  = TO_MILLI_INT( p_viewpoint->f_zoom ),
+    };
+
+    if ( p_mi->viewpoint.fov + update.fov <= 0 )
+    {
+        libvlc_printerr ("Field of view <= 0");
+        return -1;
+    }
+    if ( p_mi->viewpoint.fov + update.fov >= TO_MILLI_INT(180) )
+    {
+        libvlc_printerr ("Field of view >= 180");
+        return -1;
+    }
+
+    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
+    if( p_input_thread != NULL )
+    {
+        if (input_SetViewpoint( p_input_thread, &update, false ) != VLC_SUCCESS)
+        {
+            vlc_object_release( p_input_thread );
+            return -1;
+        }
+        vlc_object_release( p_input_thread );
+    }
+
+    p_mi->viewpoint.yaw   +=  update.yaw;
+    p_mi->viewpoint.pitch +=  update.pitch;
+    p_mi->viewpoint.roll  +=  update.roll;
+    p_mi->viewpoint.zoom  +=  update.zoom;
+    p_mi->viewpoint.fov   +=  update.fov;
+
+    return 0;
+}
+
 int libvlc_video_get_spu( libvlc_media_player_t *p_mi )
 {
     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
diff --git a/test/Makefile.am b/test/Makefile.am
index e47430e..2c86751 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -83,7 +83,7 @@ test_libvlc_media_list_player_LDADD = $(LIBVLC)
 test_libvlc_media_list_SOURCES = libvlc/media_list.c
 test_libvlc_media_list_LDADD = $(LIBVLC)
 test_libvlc_media_player_SOURCES = libvlc/media_player.c
-test_libvlc_media_player_LDADD = $(LIBVLC)
+test_libvlc_media_player_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_libvlc_media_discoverer_SOURCES = libvlc/media_discoverer.c
 test_libvlc_media_discoverer_LDADD = $(LIBVLC)
 test_libvlc_renderer_discoverer_SOURCES = libvlc/renderer_discoverer.c
diff --git a/test/libvlc/media_player.c b/test/libvlc/media_player.c
index f3198b5..6db58a9 100644
--- a/test/libvlc/media_player.c
+++ b/test/libvlc/media_player.c
@@ -23,6 +23,9 @@
 
 #include "test.h"
 
+#include <vlc_common.h>
+#include <vlc_threads.h> /* for msleep */
+
 static void wait_playing(libvlc_media_player_t *mp)
 {
     libvlc_state_t state;
@@ -190,6 +193,105 @@ static void test_media_player_pause_stop(const char** argv, int argc)
     libvlc_release (vlc);
 }
 
+static void
+player_has_es(const struct libvlc_event_t *p_ev, void *p_data)
+{
+    (void) p_ev;
+    vlc_sem_t *p_sem = p_data;
+    vlc_sem_post(p_sem);
+}
+
+static void wait_done(void *p_data)
+{
+    vlc_sem_t *p_sem = p_data;
+    vlc_sem_post(p_sem);
+}
+
+static void test_media_player_viewpoint(const char** argv, int argc)
+{
+    libvlc_instance_t *vlc;
+    libvlc_media_t *md;
+    libvlc_media_player_t *mi;
+    const char * file = test_default_video;
+
+    log ("Testing viewpoint for %s\n", file);
+
+    vlc = libvlc_new (argc, argv);
+    assert (vlc != NULL);
+
+    md = libvlc_media_new_path (vlc, file);
+    assert (md != NULL);
+
+    mi = libvlc_media_player_new_from_media (md);
+    assert (mi != NULL);
+
+    libvlc_media_release (md);
+
+    libvlc_video_viewpoint_t *p_viewpoint = libvlc_video_new_viewpoint();
+    assert(p_viewpoint != NULL);
+
+    /* test without the file loaded */
+    assert(!libvlc_video_get_viewpoint(mi, p_viewpoint));
+    assert(p_viewpoint->f_yaw == 0.0f);
+    libvlc_free(p_viewpoint);
+
+    p_viewpoint = libvlc_video_new_viewpoint();
+    assert(p_viewpoint != NULL);
+    p_viewpoint->f_yaw = 180.f;
+    assert(!libvlc_video_set_viewpoint(mi, p_viewpoint));
+    assert(p_viewpoint->f_yaw == 180.f);
+
+    libvlc_free(p_viewpoint);
+    p_viewpoint = libvlc_video_new_viewpoint();
+    assert(p_viewpoint != NULL);
+
+    assert(!libvlc_video_get_viewpoint(mi, p_viewpoint));
+    printf("yaw %f\n", p_viewpoint->f_yaw);
+    assert(p_viewpoint->f_yaw == 180.f);
+
+    libvlc_media_player_play (mi);
+
+    vlc_sem_t es_selected;
+    vlc_sem_init(&es_selected, 0);
+
+    libvlc_event_manager_t * em = libvlc_media_player_event_manager(mi);
+    int val = libvlc_event_attach(em, libvlc_MediaPlayerVout, player_has_es, &es_selected);
+    assert(val == 0);
+
+    log ("Waiting for Vout\n");
+    vlc_sem_wait(&es_selected);
+    log ("Vout found\n");
+
+    libvlc_event_detach(em, libvlc_MediaPlayerVout, player_has_es, &es_selected);
+
+    assert(!libvlc_video_get_viewpoint(mi, p_viewpoint));
+    assert(p_viewpoint->f_yaw == 180.f);
+
+    libvlc_free(p_viewpoint);
+    p_viewpoint = libvlc_video_new_viewpoint();
+    assert(p_viewpoint != NULL);
+
+    p_viewpoint->f_yaw -= 30.f;
+    assert(!libvlc_video_set_viewpoint(mi, p_viewpoint));
+
+    /* let the value propagate */
+    vlc_timer_t done_timer;
+    int ret = vlc_timer_create( &done_timer, wait_done, &es_selected );
+    assert(!ret);
+    vlc_timer_schedule( done_timer, false, 1, CLOCK_FREQ / 5 );
+    vlc_sem_wait(&es_selected);
+    vlc_timer_destroy( done_timer );
+    vlc_sem_destroy(&es_selected);
+
+    assert(!libvlc_video_get_viewpoint(mi, p_viewpoint));
+    assert(p_viewpoint->f_yaw == 150.f);
+
+    libvlc_free(p_viewpoint);
+
+    libvlc_media_player_stop (mi);
+    libvlc_media_player_release (mi);
+    libvlc_release (vlc);
+}
 
 int main (void)
 {
@@ -198,6 +300,7 @@ int main (void)
     test_media_player_set_media (test_defaults_args, test_defaults_nargs);
     test_media_player_play_stop (test_defaults_args, test_defaults_nargs);
     test_media_player_pause_stop (test_defaults_args, test_defaults_nargs);
+    test_media_player_viewpoint (test_defaults_args, test_defaults_nargs);
 
     return 0;
 }
-- 
2.10.1



More information about the vlc-devel mailing list