[vlc-devel] [PATCH 01/11] vout: trigger filters commands
Thomas Guillem
thomas at gllm.fr
Tue May 30 13:39:50 CEST 2017
On Mon, May 29, 2017, at 19:23, Rémi Denis-Courmont wrote:
> Le maanantaina 29. toukokuuta 2017, 18.52.55 EEST Thomas Guillem a écrit
> :
> > ---
> > src/video_output/video_output.c | 94
> > +++++++++++++++++++++++++++++++++++++++- src/video_output/vout_internal.h |
> > 1 +
> > 2 files changed, 94 insertions(+), 1 deletion(-)
> >
> > diff --git a/src/video_output/video_output.c
> > b/src/video_output/video_output.c index 730b902b24..a1d3ec1911 100644
> > --- a/src/video_output/video_output.c
> > +++ b/src/video_output/video_output.c
> > @@ -46,12 +46,14 @@
> > #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"
> >
> > /**************************************************************************
> > *** * Local prototypes
> > @@ -140,6 +142,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 +653,85 @@ int vout_HideWindowMouse(vout_thread_t *vout, bool
> > hide) }
> >
> > /* */
> > +struct filter_callback
> > +{
> > + filter_t * filter;
> > + const char *psz_name;
> > + int type;
>
> You should not need to track the type. Just use var_Set().
OK
>
> > +};
> > +
> > +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_SetChecked(callback->filter, psz_var, callback->type, 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->psz_name, FilterProxyCallback,
> > callback);
> > + var_Destroy(vout, callback->psz_name);
> > + free(callback);
> > + }
> > + vlc_array_clear(&vout->p->filter.callbacks);
> > +}
> > +
> > +static int 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. */ +
> > + vlc_plugin_t *plugin = filter->p_module->plugin;
> > + for (size_t i = 0; i < plugin->conf.size; ++i)
> > + {
> > + module_config_t *config = &plugin->conf.items[i];
> > + switch (config->i_type)
> > + {
> > + case CONFIG_ITEM_FLOAT:
> > + case CONFIG_ITEM_INTEGER:
> > + case CONFIG_ITEM_BOOL:
> > + case CONFIG_ITEM_STRING:
> > + break;
> > + default:
> > + continue;
> > + }
>
> > + int var_type = var_Type(filter, config->psz_name);
>
> AFAIK, a specific filter instance might not register a callback, or even
> create a variable at all, out of a given configuration item of the module
> that
> is was intantiated from. Also conversely, it might create a variable and
> register a callback for an item from another module. And finally, this
> will
> not preserve limits and what-not, such as if var_Change() is used.
>
> If you want to use introspection to avoid patching all filters, you are
> most
> probably better off introspecting the filter object variables than the
> module
> items.
OK, I'll add a new core only function: var_GetAllNames().
>
> > + 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->psz_name, config->psz_name) != 0);
> > + }
> > +#endif
> > + struct filter_callback *callback = malloc(sizeof(*callback));
> > + if (unlikely(callback == NULL))
> > + return VLC_ENOMEM;
> > +
> > + callback->filter = filter;
> > + callback->psz_name = config->psz_name;
> > + callback->type = var_type & VLC_VAR_CLASS;
> > + vlc_array_append(&vout->p->filter.callbacks, callback);
> > +
> > + var_Create(vout, callback->psz_name, var_type |
> > VLC_VAR_DOINHERIT);
> > + var_AddCallback(vout, callback->psz_name,
> > FilterProxyCallback,
> > + callback);
>
> Note that this will inherit the same race conditions as
> vlc_object_find_name()
> had. Also I don´t know what would happen if a filter removed a variable
> before
> deactivation.
>
> This is acceptable for the GUI, since it is not a regression there. But
> it
> would not scale up to programmatic use through LibVLC.
This function is executed just after the successful probing of a filter
module.
For me, there is a race only if a filter destroy/change a variable from
a background thread, no ?
There is no such filters doing it right now ?
>
> > + }
> > + }
> > + return VLC_SUCCESS;
> > +}
> > +
> > static picture_t *VoutVideoFilterInteractiveNewPicture(filter_t *filter)
> > {
> > vout_thread_t *vout = filter->owner.sys;
> > @@ -702,6 +785,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 +854,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 +1519,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 +1545,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/
>
> _______________________________________________
> 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