[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