[vlc-devel] [PATCHv3 01/12] add a new type of module: vlc_renderer
Steve Lhomme
robux4 at gmail.com
Thu Mar 31 10:16:12 CEST 2016
On Wed, Mar 30, 2016 at 8:15 PM, Rémi Denis-Courmont <remi at remlab.net> wrote:
> On Tuesday 29 March 2016 15:06:32 Thomas Guillem wrote:
>> 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)
>
> Again: don´t do that. This function does not work and it never will.
>
>> +{
>> + 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;
>> +}
So the solution is to copy all these lines everywhere we need them ?
With possible bugs are at every different copy ?
And yes it works as it is and we use it.
> --
> Rémi Denis-Courmont
> http://www.remlab.net/
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list