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

Steve Lhomme robux4 at videolabs.io
Tue Sep 20 10:11:10 CEST 2016


--
replaces https://patches.videolan.org/patch/14420/
* redo the API so that the structure is allocated and released via the API
* add missing libvlc.sym changes
* add API tests
* media_player variables are not inherited

replaces https://patches.videolan.org/patch/14457/
* warn the user the structure must be allocated with get_viewpoint()
* get_viewpoint() returns the allocated structure directly
* use libvlc_free instead of a release function
* move the structure so it's in a libvlc video doc

replaces https://patches.videolan.org/patch/14468/
* use an API entry to allocate the structure
* get/set individually on the vout number, if no vout set the local variable
  that will be inherited when vout(s) will be created
* get/set return error values and set an error string

replaces https://patches.videolan.org/patch/14475/
* use msleep instead of sleep to wait for the vout in tests
* use vlc_viewpoint rather than "viepoint"

replaces https://patches.videolan.org/patch/14482/
* remove a NULL pointer check
* more value checks in media_player tests

replaces https://patches.videolan.org/patch/14491/
* the values are in radians

replaces https://patches.videolan.org/patch/14482/
* rename vlc_viewpoint to vlc_viewpoint_t
---
 include/vlc/libvlc_media_player.h |  61 +++++++++++++++++++++
 lib/libvlc.sym                    |   3 ++
 lib/media_player.c                |   1 +
 lib/video.c                       | 108 ++++++++++++++++++++++++++++++++++++++
 test/libvlc/media_player.c        |  67 +++++++++++++++++++++++
 5 files changed, 240 insertions(+)

diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 2718a33..5b96588 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -1127,6 +1127,67 @@ 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 radians */
+    float f_pitch;         /**< view point pitch in radians */
+    float f_roll;          /**< view point roll in radians */
+} 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();
+
+/**
+ * Get current video viewpoint.
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \param p_mi the media player
+ * \param num number of video output (typically 0 for the first/only one)
+ * \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
+ * \return 1 if the structure was filled, 0 if the vout number doesn't match
+ * \warning the call is synchronous and may not return the value just set with
+ *          libvlc_video_set_viewpoint().
+ *
+ * \libvlc_return_bool
+ */
+LIBVLC_API int libvlc_video_get_viewpoint( libvlc_media_player_t *p_mi,
+                                           unsigned num,
+                                           libvlc_video_viewpoint_t *p_viewpoint );
+
+/**
+ * Set new video viewpoint information.
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \param p_mi the media player
+ * \param num number of video output (typically 0 for the first/only one)
+ * \param p_viewpoint new video viewpoint allocated via libvlc_video_new_viewpoint()
+ *                    or NULL to reset to default.
+ * \return -1 if an error was detected, 0 otherwise.
+ *
+ * \note if no file is playing the value is set on the media player.
+ * \note if the vout number doesn't match any vout, the value is discarded.
+ * \note the values are set asynchronously, all at once.
+ */
+LIBVLC_API int libvlc_video_set_viewpoint( libvlc_media_player_t *p_mi,
+                                            unsigned num,
+                                            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 733a4dd..1074d7d 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -271,6 +271,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 69d3523..4d5b35c 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -640,6 +640,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     var_Create (mp, "zoom", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
     var_Create (mp, "aspect-ratio", VLC_VAR_STRING);
     var_Create (mp, "crop", VLC_VAR_STRING);
+    var_Create (mp, "viewpoint", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
     var_Create (mp, "deinterlace", VLC_VAR_INTEGER);
     var_Create (mp, "deinterlace-mode", VLC_VAR_STRING);
 
diff --git a/lib/video.c b/lib/video.c
index b2c9b34..fa8260d 100644
--- a/lib/video.c
+++ b/lib/video.c
@@ -281,6 +281,114 @@ void libvlc_video_set_aspect_ratio( libvlc_media_player_t *p_mi,
     free (pp_vouts);
 }
 
+libvlc_video_viewpoint_t *libvlc_video_new_viewpoint()
+{
+    return calloc(1, sizeof(libvlc_video_viewpoint_t));
+}
+
+int libvlc_video_get_viewpoint( libvlc_media_player_t *p_mi, unsigned num,
+                                libvlc_video_viewpoint_t *p_viewpoint )
+{
+    vout_thread_t *p_vout = NULL;
+    size_t n;
+    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
+    if (pp_vouts == NULL)
+    {
+        /* no vout, read the p_mi value */
+        char *psz_viewpoint = var_GetNonEmptyString( p_mi, "viewpoint" );
+        if ( psz_viewpoint == NULL ||
+             sscanf( psz_viewpoint, "%f:%f:%f",
+                     &p_viewpoint->f_yaw, &p_viewpoint->f_pitch, &p_viewpoint->f_roll) != 3) {
+            p_viewpoint->f_yaw = p_viewpoint->f_pitch = p_viewpoint->f_roll = 0.0f;
+        }
+    }
+    else if (num >= n)
+    {
+        /* unknown vout, read nothing */
+        for (size_t i = 0; i < n; i++)
+            vlc_object_release (pp_vouts[i]);
+        free (pp_vouts);
+        libvlc_printerr("unknown vout number %d", num);
+        return 0;
+    }
+    else
+    {
+        /* read the value from the specified vout */
+        p_vout = pp_vouts[num];
+        for (size_t i = 0; i < n; i++)
+        {
+            if (i != num)
+                vlc_object_release (pp_vouts[i]);
+        }
+        free (pp_vouts);
+
+        vlc_viewpoint_t viewpoint;
+        vout_GetViewpoint( p_vout, &viewpoint );
+        vlc_object_release (p_vout);
+
+        p_viewpoint->f_yaw   = viewpoint.f_yaw;
+        p_viewpoint->f_pitch = viewpoint.f_pitch;
+        p_viewpoint->f_roll  = viewpoint.f_roll;
+    }
+
+    return 1;
+}
+
+int libvlc_video_set_viewpoint( libvlc_media_player_t *p_mi,
+                                 unsigned num,
+                                 const libvlc_video_viewpoint_t *p_viewpoint )
+{
+    vout_thread_t *p_vout = NULL;
+    size_t n;
+    vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
+    if (pp_vouts == NULL)
+    {
+        /* no vout, set the mi value */
+        char psz_viewpoint[4 * 13];
+        if (p_viewpoint == NULL)
+            psz_viewpoint[0] = '\0';
+        else
+            sprintf( psz_viewpoint, "%.7f:%.7f:%.7f",
+                     p_viewpoint->f_yaw, p_viewpoint->f_pitch, p_viewpoint->f_roll  );
+        int err = var_SetString (p_mi, "viewpoint", psz_viewpoint);
+        if (err != VLC_SUCCESS)
+        {
+            libvlc_printerr("failed to set the viewpoint (%d)", err);
+            return -1;
+        }
+    }
+    else if (num >= n)
+    {
+        /* unknown vout, write nothing */
+        for (size_t i = 0; i < n; i++)
+            vlc_object_release (pp_vouts[i]);
+        free (pp_vouts);
+        libvlc_printerr("unknown vout number %d", num);
+        return -1;
+    }
+    else
+    {
+        /* write the value from the specified vout */
+        p_vout = pp_vouts[num];
+        for (size_t i = 0; i < n; i++)
+        {
+            if (i != num)
+                vlc_object_release (pp_vouts[i]);
+        }
+        free (pp_vouts);
+
+        vlc_viewpoint_t viewpoint = {
+            .f_yaw   =   p_viewpoint->f_yaw,
+            .f_pitch =   p_viewpoint->f_pitch,
+            .f_roll  =   p_viewpoint->f_roll,
+        };
+        vout_SetViewpoint(p_vout, &viewpoint);
+        vlc_object_release (p_vout);
+    }
+
+    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/libvlc/media_player.c b/test/libvlc/media_player.c
index f3198b5..fe913fe 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,69 @@ static void test_media_player_pause_stop(const char** argv, int argc)
     libvlc_release (vlc);
 }
 
+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, 0, p_viewpoint));
+    assert(libvlc_video_get_viewpoint(mi, 16, p_viewpoint));
+
+    p_viewpoint->f_yaw = 1.57f;
+    assert(!libvlc_video_set_viewpoint(mi, 0, p_viewpoint));
+    libvlc_free(p_viewpoint);
+    p_viewpoint = libvlc_video_new_viewpoint();
+    assert(p_viewpoint != NULL);
+
+    assert(libvlc_video_get_viewpoint(mi, 0, p_viewpoint));
+    assert(p_viewpoint->f_yaw == 1.57f);
+
+    libvlc_media_player_play (mi);
+    log ("Waiting for playing\n");
+    wait_playing (mi);
+
+    while ( libvlc_media_player_has_vout(mi) == 0 )
+        msleep( CLOCK_FREQ / 5 );
+    log ("Vout found\n");
+
+    assert(!libvlc_video_get_viewpoint(mi, 16, p_viewpoint));
+    assert(libvlc_video_get_viewpoint(mi, 0, p_viewpoint));
+    assert(p_viewpoint->f_yaw == 1.57f);
+
+    p_viewpoint->f_yaw = 0.57f;
+    assert(!libvlc_video_set_viewpoint(mi, 0, p_viewpoint));
+
+    msleep( CLOCK_FREQ / 5 ); /* let the value propagate */
+
+    assert(libvlc_video_get_viewpoint(mi, 0, p_viewpoint));
+    assert(p_viewpoint->f_yaw == 0.57f);
+
+    assert(!libvlc_video_get_viewpoint(mi, libvlc_media_player_has_vout(mi), p_viewpoint));
+    libvlc_free(p_viewpoint);
+
+    libvlc_media_player_stop (mi);
+    libvlc_media_player_release (mi);
+    libvlc_release (vlc);
+}
 
 int main (void)
 {
@@ -198,6 +264,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.8.2



More information about the vlc-devel mailing list