[vlc-devel] [PATCHv3 01/12] add a new type of module: vlc_renderer
Thomas Guillem
thomas at gllm.fr
Tue Mar 29 15:06:32 CEST 2016
This new type of module will be used by renderers (chromecast, UPnP Renderer,
miracast, airport, DIAL, ConeCast) to configure a VLC input_thread for
rendering, like configuring a sout according to the renderer ip and
capabilities.
This API is experimental and has been tested only for chromecast, it may move
in the future when implementing others renderers.
Also-by: Steve Lhomme <robux4 at videolabs.io>
---
include/vlc_common.h | 2 +
include/vlc_renderer.h | 130 ++++++++++++++++++++++++++++
src/Makefile.am | 2 +
src/libvlccore.sym | 7 ++
src/misc/renderer.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 364 insertions(+)
create mode 100644 include/vlc_renderer.h
create mode 100644 src/misc/renderer.c
diff --git a/include/vlc_common.h b/include/vlc_common.h
index 296439e..431fbb4 100644
--- a/include/vlc_common.h
+++ b/include/vlc_common.h
@@ -208,6 +208,8 @@ typedef struct playlist_item_t playlist_item_t;
typedef struct services_discovery_t services_discovery_t;
typedef struct services_discovery_sys_t services_discovery_sys_t;
typedef struct playlist_add_t playlist_add_t;
+typedef struct vlc_renderer_item vlc_renderer_item;
+typedef struct vlc_renderer vlc_renderer;
/* Modules */
typedef struct module_t module_t;
diff --git a/include/vlc_renderer.h b/include/vlc_renderer.h
new file mode 100644
index 0000000..5c462d9
--- /dev/null
+++ b/include/vlc_renderer.h
@@ -0,0 +1,130 @@
+/*****************************************************************************
+ * vlc_renderer.h: VLC renderer
+ *****************************************************************************
+ * Copyright (C) 2016 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_RENDERER_H
+#define VLC_RENDERER_H 1
+
+#include <vlc_url.h>
+
+/**
+ * @defgroup vlc_renderer VLC renderer
+ * @{
+ * @file
+ * This file declares VLC renderer structures and functions
+ * @defgroup vlc_renderer_item VLC renderer items
+ * @{
+ */
+
+typedef struct vlc_renderer_item vlc_renderer_item;
+
+#define VLC_RENDERER_CAN_AUDIO 0x0001
+#define VLC_RENDERER_CAN_VIDEO 0x0002
+
+/**
+ * Create a new renderer item
+ *
+ * @param psz_name name of the item
+ * @param psz_uri uri of the renderer item, must contains a valid protocol and
+ * a valid host
+ * @param i_flags flags for the item
+ * @return a renderer item or NULL in case of error
+ */
+VLC_API vlc_renderer_item *
+vlc_renderer_item_new(const char *psz_name, const char *psz_uri,
+ int i_flags) VLC_USED;
+
+/**
+ * Hold a renderer item, i.e. creates a new reference
+ */
+VLC_API vlc_renderer_item *
+vlc_renderer_item_hold(vlc_renderer_item *p_item);
+
+/**
+ * Releases a renderer item, i.e. decrements its reference counter
+ */
+VLC_API void
+vlc_renderer_item_release(vlc_renderer_item *p_item);
+
+/**
+ * Get the name of a renderer item
+ */
+VLC_API const char *
+vlc_renderer_item_name(const vlc_renderer_item *p_item);
+
+/**
+ * Get the host of a renderer item
+ */
+VLC_API const char *
+vlc_renderer_item_uri(const vlc_renderer_item *p_item);
+
+/**
+ * Get the flags of a renderer item
+ */
+VLC_API int
+vlc_renderer_item_flags(const vlc_renderer_item *p_item);
+
+/**
+ * Check if a renderer corresponds to this URI
+ */
+VLC_API
+bool vlc_renderer_equals(vlc_renderer *p_renderer, const char *psz_uri);
+
+/**
+ * @}
+ * @defgroup vlc_renderer_module VLC renderer module
+ * @{
+ */
+
+typedef struct vlc_renderer vlc_renderer;
+typedef struct vlc_renderer_sys vlc_renderer_sys;
+struct vlc_renderer
+{
+ VLC_COMMON_MEMBERS
+ /**
+ */
+ module_t *p_module;
+ vlc_renderer_sys *p_sys;
+
+ vlc_url_t target;
+
+ /**
+ * Handle a new input thread.
+ *
+ * p_renderer->target is a valid url with a valid psz_protocol and valid
+ * psz_host.
+ *
+ * @param p_input new input to handle, or NULL to stop the current one.
+ */
+ int (*pf_set_input)(vlc_renderer *p_renderer, input_thread_t *p_input);
+};
+
+/** @} @} */
+
+/* Internal API */
+
+/* Release with vlc_object_release */
+vlc_renderer *
+vlc_renderer_new(vlc_object_t *p_obj, const char *psz_renderer);
+#define vlc_renderer_new(a, b) vlc_renderer_new(VLC_OBJECT(a), b)
+
+int
+vlc_renderer_set_input(vlc_renderer *p_renderer, input_thread_t *p_input);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ee185f..4d5fd6c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -82,6 +82,7 @@ pluginsinclude_HEADERS = \
../include/vlc_services_discovery.h \
../include/vlc_fingerprinter.h \
../include/vlc_interrupt.h \
+ ../include/vlc_renderer.h \
../include/vlc_sout.h \
../include/vlc_spu.h \
../include/vlc_stream.h \
@@ -444,6 +445,7 @@ SOURCES_libvlc_common = \
misc/interrupt.h \
misc/interrupt.c \
misc/keystore.c \
+ misc/renderer.c \
modules/modules.h \
modules/modules.c \
modules/bank.c \
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 0d69d14..a6f292e 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -734,3 +734,10 @@ addons_manager_Remove
addon_entry_New
addon_entry_Hold
addon_entry_Release
+vlc_renderer_item_new
+vlc_renderer_item_hold
+vlc_renderer_item_release
+vlc_renderer_equals
+vlc_renderer_item_name
+vlc_renderer_item_uri
+vlc_renderer_item_flags
diff --git a/src/misc/renderer.c b/src/misc/renderer.c
new file mode 100644
index 0000000..2a64f59
--- /dev/null
+++ b/src/misc/renderer.c
@@ -0,0 +1,223 @@
+/*****************************************************************************
+ * renderer.c: Renderers
+ *****************************************************************************
+ * Copyright (C) 2016 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <vlc_common.h>
+#include <vlc_atomic.h>
+#include <vlc_renderer.h>
+#include <vlc_modules.h>
+#include <libvlc.h>
+#include "../lib/libvlc_internal.h"
+
+struct vlc_renderer_item
+{
+ char *psz_name;
+ char *psz_uri;
+ int i_flags;
+ atomic_uint refs;
+};
+
+struct renderer_priv
+{
+ vlc_renderer s;
+ bool b_has_input;
+};
+
+vlc_renderer_item *
+vlc_renderer_item_new(const char *psz_name, const char *psz_uri, int i_flags)
+{
+ assert(psz_uri != NULL);
+ vlc_renderer_item *p_item = NULL;
+ vlc_url_t url;
+ vlc_UrlParse(&url, psz_uri);
+
+ if (url.psz_protocol == NULL || url.psz_host == NULL)
+ goto error;
+
+ p_item = calloc(1, sizeof(vlc_renderer_item));
+ if (unlikely(p_item == NULL))
+ goto error;
+
+ if (psz_name != NULL)
+ p_item->psz_name = strdup(psz_name);
+ else if (asprintf(&p_item->psz_name, "%s (%s)", url.psz_protocol,
+ url.psz_host) == -1)
+ p_item->psz_name = NULL;
+ if (p_item->psz_name == NULL)
+ goto error;
+
+ if ((p_item->psz_uri = strdup(psz_uri)) == NULL)
+ {
+ free(p_item->psz_name);
+ goto error;
+ }
+
+ p_item->i_flags = i_flags;
+ atomic_init(&p_item->refs, 1);
+ vlc_UrlClean(&url);
+ return p_item;
+
+error:
+ vlc_UrlClean(&url);
+ free(p_item);
+ return NULL;
+}
+
+const char *
+vlc_renderer_item_name(const vlc_renderer_item *p_item)
+{
+ assert(p_item != NULL);
+
+ return p_item->psz_name;
+}
+
+const char *
+vlc_renderer_item_uri(const vlc_renderer_item *p_item)
+{
+ assert(p_item != NULL);
+
+ return p_item->psz_uri;
+}
+
+int
+vlc_renderer_item_flags(const vlc_renderer_item *p_item)
+{
+ assert(p_item != NULL);
+
+ return p_item->i_flags;
+}
+
+vlc_renderer_item *
+vlc_renderer_item_hold(vlc_renderer_item *p_item)
+{
+ assert(p_item != NULL);
+
+ atomic_fetch_add(&p_item->refs, 1);
+ return p_item;
+}
+
+void
+vlc_renderer_item_release(vlc_renderer_item *p_item)
+{
+ assert(p_item != NULL);
+
+ if (atomic_fetch_sub(&p_item->refs, 1) != 1)
+ return;
+ free(p_item->psz_name);
+ free(p_item->psz_uri);
+ free(p_item);
+}
+
+static inline struct renderer_priv *
+renderer_priv(vlc_renderer *p_renderer)
+{
+ return (struct renderer_priv *)p_renderer;
+}
+
+static void
+renderer_destructor(vlc_object_t *p_obj)
+{
+ vlc_renderer *p_renderer = (vlc_renderer *)p_obj;
+ struct renderer_priv *p_priv = renderer_priv(p_renderer);
+
+ if (p_priv->b_has_input)
+ vlc_renderer_set_input(p_renderer, NULL);
+
+ module_unneed(p_renderer, p_renderer->p_module);
+
+ vlc_UrlClean(&p_renderer->target);
+}
+
+#undef vlc_renderer_new
+vlc_renderer *
+vlc_renderer_new(vlc_object_t *p_obj, const char *psz_renderer)
+{
+ assert(p_obj != NULL && psz_renderer != NULL);
+ struct renderer_priv *p_priv =
+ vlc_custom_create(p_obj, sizeof (*p_priv), "renderer");
+ if (p_priv == NULL)
+ return NULL;
+ vlc_renderer *p_renderer = &p_priv->s;
+
+ vlc_UrlParse(&p_renderer->target, psz_renderer);
+ if (p_renderer->target.psz_protocol == NULL
+ || p_renderer->target.psz_host == NULL)
+ {
+ vlc_object_release(p_renderer);
+ return NULL;
+ }
+ p_renderer->p_module = module_need(p_renderer, "renderer",
+ p_renderer->target.psz_protocol, true);
+ if (p_renderer->p_module == NULL)
+ {
+ vlc_UrlClean(&p_renderer->target);
+ vlc_object_release(p_renderer);
+ return NULL;
+ }
+ assert(p_renderer->pf_set_input);
+ vlc_object_set_destructor(p_renderer, renderer_destructor);
+
+ return p_renderer;
+}
+
+int
+vlc_renderer_set_input(vlc_renderer *p_renderer, input_thread_t *p_input)
+{
+ assert(p_renderer != NULL);
+ struct renderer_priv *p_priv = renderer_priv(p_renderer);
+
+ int i_ret = p_renderer->pf_set_input(p_renderer, p_input);
+ if (i_ret == VLC_SUCCESS)
+ p_priv->b_has_input = p_input != NULL;
+ else
+ p_priv->b_has_input = false;
+
+ return i_ret;
+}
+
+bool
+vlc_renderer_equals(vlc_renderer *p_renderer, const char *psz_renderer)
+{
+ assert(p_renderer->target.psz_protocol != NULL
+ && p_renderer->target.psz_host != NULL);
+
+ vlc_url_t url;
+ vlc_UrlParse(&url, psz_renderer);
+ if (url.psz_protocol == NULL || url.psz_host == NULL)
+ {
+ vlc_UrlClean(&url);
+ return false;
+ }
+ const char *psz_option1 = p_renderer->target.psz_option != NULL
+ ? p_renderer->target.psz_option : "";
+ const char *psz_option2 = url.psz_option != NULL ? url.psz_option : "";
+ bool b_ret = !strcmp(p_renderer->target.psz_protocol, url.psz_protocol)
+ && !strcmp(p_renderer->target.psz_host, url.psz_host)
+ && !strcmp(psz_option1, psz_option2)
+ && p_renderer->target.i_port == url.i_port;
+ vlc_UrlClean(&url);
+ return b_ret;
+}
--
2.8.0.rc3
More information about the vlc-devel
mailing list