[vlc-devel] [PATCHv2 05/18] vout: trigger filters commands
Thomas Guillem
thomas at gllm.fr
Tue May 30 18:40:55 CEST 2017
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);
+ }
+ 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;
/* */
--
2.11.0
More information about the vlc-devel
mailing list