[vlc-devel] [PATCHv2 05/18] vout: trigger filters commands
Rémi Denis-Courmont
remi at remlab.net
Tue May 30 21:37:53 CEST 2017
Le tiistaina 30. toukokuuta 2017, 18.40.55 EEST Thomas Guillem a écrit :
> The vout now duplicates every command variables of spawned filters in order
> to trigger events directly from the vout.
> ---
> src/video_output/video_output.c | 91
> +++++++++++++++++++++++++++++++++++++++- src/video_output/vout_internal.h |
> 1 +
> 2 files changed, 91 insertions(+), 1 deletion(-)
>
> diff --git a/src/video_output/video_output.c
> b/src/video_output/video_output.c index 730b902b24..1f30797a5a 100644
> --- a/src/video_output/video_output.c
> +++ b/src/video_output/video_output.c
> @@ -46,12 +46,15 @@
> #include <vlc_spu.h>
> #include <vlc_vout_osd.h>
> #include <vlc_image.h>
> +#include <vlc_plugin.h>
>
> #include <libvlc.h>
> #include "vout_internal.h"
> #include "interlacing.h"
> #include "display.h"
> #include "window.h"
> +#include "../modules/modules.h"
> +#include "../misc/variables.h"
>
> /**************************************************************************
> *** * Local prototypes
> @@ -140,6 +143,8 @@ static vout_thread_t *VoutCreate(vlc_object_t *object,
>
> vout_snapshot_Init(&vout->p->snapshot);
>
> + vlc_array_init(&vout->p->filter.callbacks);
> +
> /* Initialize locks */
> vlc_mutex_init(&vout->p->filter.lock);
> vlc_mutex_init(&vout->p->spu_lock);
> @@ -649,6 +654,81 @@ int vout_HideWindowMouse(vout_thread_t *vout, bool
> hide) }
>
> /* */
> +struct filter_callback
> +{
> + filter_t *filter;
> + char *name;
> +};
> +
> +static int FilterProxyCallback(vlc_object_t *p_this, char const *psz_var,
> + vlc_value_t oldval, vlc_value_t newval,
> + void *p_data)
> +{
> + (void) p_this; (void) oldval;
> + struct filter_callback *callback = p_data;
> + var_Set(callback->filter, psz_var, newval);
> + return 0;
> +}
> +
> +static void ThreadDelFilterCallbacks(vout_thread_t *vout)
> +{
> + for (size_t i = 0; i < vlc_array_count(&vout->p->filter.callbacks);
> ++i) + {
> + struct filter_callback *callback =
> + vlc_array_item_at_index(&vout->p->filter.callbacks, i);
> + var_DelCallback(vout, callback->name, FilterProxyCallback,
> callback); + var_Destroy(vout, callback->name);
> + free(callback->name);
> + free(callback);
> + }
> + vlc_array_clear(&vout->p->filter.callbacks);
> +}
> +
> +static void ThreadAddFilterCallbacks(vout_thread_t *vout, filter_t *filter)
> +{
> + /* Duplicate every command variables from the filter to the vout, and
> add a + * proxy callback to trigger filters events from the vout. */ +
> + char **names = var_GetAllNames(VLC_OBJECT(filter));
> + if (names == NULL)
> + return;
> +
> + for (char **pname = names; *pname != NULL; pname++)
> + {
> + char *name = *pname;
> + int var_type = var_Type(filter, name);
> + if (!(var_type & VLC_VAR_ISCOMMAND))
> + {
> +#ifndef NDEBUG
> + /* Make sure that each option is unique */
> + for (size_t i = 0; i <
> vlc_array_count(&vout->p->filter.callbacks); + ++i)
> + {
> + struct filter_callback *callback =
> + vlc_array_item_at_index(&vout->p->filter.callbacks, i);
> + assert(strcmp(callback->name, name) != 0);
> + }
> +#endif
> + struct filter_callback *callback = malloc(sizeof(*callback));
> + if (unlikely(callback == NULL))
> + {
> + free(name);
> + continue;
> + }
> +
> + callback->filter = filter;
> + callback->name = name;
> + vlc_array_append(&vout->p->filter.callbacks, callback);
> +
> + var_Create(vout, callback->name, var_type | VLC_VAR_DOINHERIT);
> + var_AddCallback(vout, callback->name, FilterProxyCallback,
> callback);
Passing filter as opaque data would seem more logical and simpler. And if you
assume that the set of variables does not change, you probably don´t even need
the array: you can reiterate at deletion.
> + }
> + else
> + free(name);
> + }
> + free(names);
> +}
> +
> static picture_t *VoutVideoFilterInteractiveNewPicture(filter_t *filter)
> {
> vout_thread_t *vout = filter->owner.sys;
> @@ -702,6 +782,7 @@ static void ThreadChangeFilters(vout_thread_t *vout,
> bool is_locked)
> {
> ThreadFilterFlush(vout, is_locked);
> + ThreadDelFilterCallbacks(vout);
>
> vlc_array_t array_static;
> vlc_array_t array_interactive;
> @@ -770,10 +851,16 @@ static void ThreadChangeFilters(vout_thread_t *vout,
> for (size_t i = 0; i < vlc_array_count(array); i++) {
> vout_filter_t *e = vlc_array_item_at_index(array, i);
> msg_Dbg(vout, "Adding '%s' as %s", e->name, a == 0 ? "static" :
> "interactive"); - if (!filter_chain_AppendFilter(chain, e->name,
> e->cfg, NULL, NULL)) { + filter_t *filter =
> filter_chain_AppendFilter(chain, e->name, e->cfg, +
> NULL, NULL);
> + if (filter)
> + ThreadAddFilterCallbacks(vout, filter);
> + else
> + {
> msg_Err(vout, "Failed to add filter '%s'", e->name);
> config_ChainDestroy(e->cfg);
> }
> +
> free(e->name);
> free(e);
> }
> @@ -1429,6 +1516,7 @@ static int ThreadStart(vout_thread_t *vout,
> vout_display_state_t *state) video_format_Print(VLC_OBJECT(vout), "original
> format", &vout->p->original); return VLC_SUCCESS;
> error:
> + ThreadDelFilterCallbacks(vout);
> if (vout->p->filter.chain_interactive != NULL)
> filter_chain_Delete(vout->p->filter.chain_interactive);
> if (vout->p->filter.chain_static != NULL)
> @@ -1454,6 +1542,7 @@ static void ThreadStop(vout_thread_t *vout,
> vout_display_state_t *state) }
>
> /* Destroy the video filters2 */
> + ThreadDelFilterCallbacks(vout);
> filter_chain_Delete(vout->p->filter.chain_interactive);
> filter_chain_Delete(vout->p->filter.chain_static);
> video_format_Clean(&vout->p->filter.format);
> diff --git a/src/video_output/vout_internal.h
> b/src/video_output/vout_internal.h index 400bcb8b61..cb64544d3d 100644
> --- a/src/video_output/vout_internal.h
> +++ b/src/video_output/vout_internal.h
> @@ -125,6 +125,7 @@ struct vout_thread_sys_t
> struct filter_chain_t *chain_static;
> struct filter_chain_t *chain_interactive;
> bool has_deint;
> + vlc_array_t callbacks;
> } filter;
>
> /* */
--
雷米‧德尼-库尔蒙
https://www.remlab.net/
More information about the vlc-devel
mailing list