[vlc-devel] [PATCHv2 05/18] vout: trigger filters commands

Thomas Guillem thomas at gllm.fr
Wed May 31 10:01:25 CEST 2017



On Tue, May 30, 2017, at 21:37, Rémi Denis-Courmont wrote:
> 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.

Ok, I'll simplify it.

> 
> > +        }
> > +        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/
> 
> _______________________________________________
> 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