[vlc-devel] [RFC] transform: add motion detection

Pierre Ynard linkfanel at yahoo.fr
Thu Nov 1 00:37:32 CET 2012


This will allow getting rid of the busy-looping, variable-hacking,
configuration-overriding motion interface. The possible issues are
getting the vout object with filter->p_parent, and not initializing all
the bits of dst? Also it will need a couple tweaks to the motion lib
first to work properly.


diff --git a/modules/video_filter/transform.c b/modules/video_filter/transform.c
index 5c2f1d1..3d374ae 100644
--- a/modules/video_filter/transform.c
+++ b/modules/video_filter/transform.c
@@ -31,10 +31,12 @@
 #   include "config.h"
 #endif
 #include <limits.h>
+#include <assert.h>
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_filter.h>
+#include "../control/motionlib.h"
 
 /*****************************************************************************
  * Module descriptor
@@ -46,11 +48,11 @@ static void Close(vlc_object_t *);
 
 #define TYPE_TEXT N_("Transform type")
 static const char * const type_list[] = { "90", "180", "270",
-    "hflip", "vflip", "transpose", "antitranspose" };
+    "hflip", "vflip", "transpose", "antitranspose", "motion" };
 static const char * const type_list_text[] = { N_("Rotate by 90 degrees"),
     N_("Rotate by 180 degrees"), N_("Rotate by 270 degrees"),
     N_("Flip horizontally"), N_("Flip vertically"),
-    N_("Transpose"), N_("Anti-transpose") };
+    N_("Transpose"), N_("Anti-transpose"), N_("Follow motion sensors") };
 
 vlc_module_begin()
     set_description(N_("Video transformation filter"))
@@ -236,12 +238,43 @@ struct filter_sys_t {
     const vlc_chroma_description_t *chroma;
     void (*plane)(plane_t *, const plane_t *);
     convert_t convert;
+    motion_sensors_t *motion;
 };
 
+#define LOW_THRESHOLD 800
+#define HIGH_THRESHOLD 1000
+
+/* Check if we need to reset the filter to a new orientation */
+static void check_motion(filter_t *filter)
+{
+    filter_sys_t *sys = filter->p_sys;
+
+    int angle = motion_get_angle(sys->motion);
+
+    if ((sys->convert == NULL
+         && (angle < -HIGH_THRESHOLD || angle > HIGH_THRESHOLD))
+        || (sys->convert == R270 && angle > -LOW_THRESHOLD)
+        || (sys->convert == R90 && angle < LOW_THRESHOLD))
+    {
+        vlc_object_t *p_vout = filter->p_parent;
+        assert(!strcmp(p_vout->psz_object_type, "video output"));
+        var_TriggerCallback(p_vout, "video-filter");
+    }
+}
+
 static picture_t *Filter(filter_t *filter, picture_t *src)
 {
     filter_sys_t *sys = filter->p_sys;
 
+    if (sys->motion != NULL)
+    {
+        check_motion(filter);
+
+        /* No rotation: the filter is a no-op */
+        if (sys->convert == NULL)
+            return src;
+    }
+
     picture_t *dst = filter_NewPicture(filter);
     if (!dst) {
         picture_Release(src);
@@ -290,6 +323,39 @@ static int Open(vlc_object_t *object)
     sys->chroma = chroma;
 
     char *type_name = var_InheritString(filter, CFG_PREFIX"type");
+
+    sys->motion = NULL;
+    if (!strcmp(type_name, "motion"))
+    {
+        free(type_name);
+        sys->motion = motion_create(VLC_OBJECT(filter));
+        if (sys->motion == NULL)
+            goto error;
+
+        int angle = motion_get_angle(sys->motion);
+        if (angle < -HIGH_THRESHOLD)
+        {
+            type_name = "270";
+            msg_Dbg(filter, "Motion detection: rotating by 270 degrees");
+        }
+        else if (angle > HIGH_THRESHOLD)
+        {
+            type_name = "90";
+            msg_Dbg(filter, "Motion detection: rotating by 90 degrees");
+        }
+        else
+        {
+            sys->convert = NULL;
+            sys->plane = NULL;
+            msg_Dbg(filter, "Motion detection: no rotation, keeping "
+                            "original orientation");
+
+            filter->p_sys           = sys;
+            filter->pf_video_filter = Filter;
+            return VLC_SUCCESS;
+        }
+    }
+
     const transform_description_t *dsc = NULL;
 
     for (size_t i = 0; i < n_transforms; i++)
@@ -303,7 +369,8 @@ static int Open(vlc_object_t *object)
                  dsc->name);
     }
 
-    free(type_name);
+    if (sys->motion == NULL)
+        free(type_name);
 
     switch (chroma->pixel_size) {
         case 1:
@@ -380,6 +447,8 @@ static int Open(vlc_object_t *object)
     filter->pf_video_mouse  = Mouse;
     return VLC_SUCCESS;
 error:
+    if (sys->motion != NULL)
+        motion_destroy(sys->motion);
     free(sys);
     return VLC_EGENERIC;
 }
@@ -389,5 +458,7 @@ static void Close(vlc_object_t *object)
     filter_t     *filter = (filter_t *)object;
     filter_sys_t *sys    = filter->p_sys;
 
+    if (sys->motion != NULL)
+        motion_destroy(sys->motion);
     free(sys);
 }


Regards,

-- 
Pierre Ynard
"Une âme dans un corps, c'est comme un dessin sur une feuille de papier."



More information about the vlc-devel mailing list