[vlc-devel] [PATCH 14/14] libvlc: add the API needed to set/get the viewpoint in 360° videos
Steve Lhomme
robux4 at videolabs.io
Fri Sep 30 18:36:25 CEST 2016
---
include/vlc/libvlc_media_player.h | 54 ++++++++++++++++++++++
lib/libvlc.sym | 3 ++
lib/media_player.c | 10 +++++
lib/media_player_internal.h | 1 +
lib/video.c | 52 ++++++++++++++++++++++
test/Makefile.am | 2 +-
test/libvlc/media_player.c | 94 +++++++++++++++++++++++++++++++++++++++
7 files changed, 215 insertions(+), 1 deletion(-)
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 9a73b4f..a0be510 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -1167,6 +1167,60 @@ 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(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
+ * \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 used by the vout yet.
+ *
+ * \libvlc_return_bool
+ */
+LIBVLC_API int libvlc_video_get_viewpoint( libvlc_media_player_t *p_mi,
+ 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 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 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 84e7189..cf79c4d 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -282,6 +282,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 9a8f73a..95afcf5 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -719,6 +719,16 @@ libvlc_media_player_new( libvlc_instance_t *instance )
if( aout != NULL )
input_resource_PutAout(mp->input.p_resource, aout);
+ char *psz_viewpoint = var_InheritString(mp, "viewpoint" );
+ if ( psz_viewpoint == NULL ||
+ sscanf( psz_viewpoint, "%f:%f:%f",
+ &mp->viewpoint.f_yaw, &mp->viewpoint.f_pitch, &mp->viewpoint.f_roll) != 3) {
+ mp->viewpoint.f_yaw = mp->viewpoint.f_pitch = mp->viewpoint.f_roll = 0.0f;
+ }
+ free(psz_viewpoint);
+
+ 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..6a0341d 100644
--- a/lib/media_player_internal.h
+++ b/lib/media_player_internal.h
@@ -53,6 +53,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; /* avoid parsing strings of floats at every get */
};
/* Media player - audio, video */
diff --git a/lib/video.c b/lib/video.c
index 8655a32..8a427f9 100644
--- a/lib/video.c
+++ b/lib/video.c
@@ -282,6 +282,58 @@ 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 )
+{
+ /* read the value from the first vout otherwise keep the local one */
+ size_t n;
+ vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
+ for (size_t i = 0; i < n; i++)
+ {
+ if (i == 0)
+ vout_GetViewpoint(pp_vouts[i], &p_mi->viewpoint);
+ vlc_object_release (pp_vouts[i]);
+ }
+ free (pp_vouts);
+
+ p_viewpoint->f_yaw = p_mi->viewpoint.f_yaw;
+ p_viewpoint->f_pitch = p_mi->viewpoint.f_pitch;
+ p_viewpoint->f_roll = p_mi->viewpoint.f_roll;
+ return 1;
+}
+
+int libvlc_video_set_viewpoint( libvlc_media_player_t *p_mi,
+ const libvlc_video_viewpoint_t *p_viewpoint )
+{
+ size_t n;
+ if (p_viewpoint == NULL)
+ {
+ p_mi->viewpoint.f_yaw = p_mi->viewpoint.f_pitch = p_mi->viewpoint.f_roll = 0.0f;
+ }
+ else
+ {
+ p_mi->viewpoint.f_yaw = p_viewpoint->f_yaw;
+ p_mi->viewpoint.f_pitch = p_viewpoint->f_pitch;
+ p_mi->viewpoint.f_roll = p_viewpoint->f_roll;
+ }
+
+ vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
+ /* write the value from all used vouts */
+ for (size_t i = 0; i < n; i++)
+ {
+ vout_SetViewpoint(pp_vouts[i], &p_mi->viewpoint);
+ vlc_object_release (pp_vouts[i]);
+ }
+ free (pp_vouts);
+
+ 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 7731782..f92fc08 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..1b58bed 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,96 @@ 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));
+
+ p_viewpoint->f_yaw = 1.57f;
+ assert(!libvlc_video_set_viewpoint(mi, p_viewpoint));
+ assert(p_viewpoint->f_yaw == 1.57f);
+
+ libvlc_free(p_viewpoint);
+ p_viewpoint = libvlc_video_new_viewpoint();
+ assert(p_viewpoint != NULL);
+
+ assert(libvlc_video_get_viewpoint(mi, p_viewpoint));
+ assert(p_viewpoint->f_yaw == 1.57f);
+
+ 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 == 1.57f);
+
+ p_viewpoint->f_yaw = 0.57f;
+ 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 == 0.57f);
+
+ libvlc_free(p_viewpoint);
+
+ libvlc_media_player_stop (mi);
+ libvlc_media_player_release (mi);
+ libvlc_release (vlc);
+}
int main (void)
{
@@ -198,6 +291,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