[gst-devel] [PATCH] RFC: v4l2: add norm property

Rob Clark rob at ti.com
Sun Mar 21 17:47:09 CET 2010


Based on a patch by Guennadi Liakhovetski.

Note: I don't actually have a device supporting tuner, so I can't really
test this myself.  I'd appreciate if someone with a tuner device could give
this a try.

---
 sys/v4l2/gstv4l2object.c |   70 +++++++++++++++++++++++++++++-----------------
 sys/v4l2/gstv4l2object.h |    5 ++-
 sys/v4l2/gstv4l2tuner.c  |   23 ++++++++++++++-
 sys/v4l2/gstv4l2tuner.h  |    5 +++
 4 files changed, 74 insertions(+), 29 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 601cc51..f205cb6 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -49,7 +49,7 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
 #define DEFAULT_PROP_DEVICE_NAME 	NULL
 #define DEFAULT_PROP_DEVICE_FD          -1
 #define DEFAULT_PROP_FLAGS              0
-#define DEFAULT_PROP_NORM               NULL
+#define DEFAULT_PROP_TV_NORM            0
 #define DEFAULT_PROP_CHANNEL            NULL
 #define DEFAULT_PROP_FREQUENCY          0
 
@@ -309,6 +309,30 @@ gst_v4l2_device_get_type (void)
   return v4l2_device_type;
 }
 
+#define GST_TYPE_V4L2_TV_NORM (gst_v4l2_tv_norm_get_type ())
+static GType
+gst_v4l2_tv_norm_get_type (void)
+{
+  static GType v4l2_tv_norm = 0;
+
+  if (!v4l2_tv_norm) {
+    static const GEnumValue tv_norms[] = {
+      {0, "none", "none"},
+      {V4L2_STD_NTSC_M, "NTSC-M", "NTSC-M"},
+      {V4L2_STD_NTSC_M_JP, "NTSC-J", "NTSC-J"},
+      {V4L2_STD_NTSC_443, "NTSC-443", "NTSC-443"},
+      {V4L2_STD_PAL_B, "PAL-B", "PAL-B"},
+      {V4L2_STD_PAL_M, "PAL-M", "PAL-M"},
+      {V4L2_STD_PAL_N, "PAL-N", "PAL-N"},
+      {0, NULL, NULL},
+    };
+
+    v4l2_tv_norm = g_enum_register_static ("V4L2_TV_norms", tv_norms);
+  }
+
+  return v4l2_tv_norm;
+}
+
 void
 gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class,
     const char *default_device)
@@ -326,6 +350,11 @@ gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class,
   g_object_class_install_property (gobject_class, PROP_FLAGS,
       g_param_spec_flags ("flags", "Flags", "Device type flags",
           GST_TYPE_V4L2_DEVICE_FLAGS, DEFAULT_PROP_FLAGS, G_PARAM_READABLE));
+  g_object_class_install_property (gobject_class, PROP_TV_NORM,
+      g_param_spec_enum ("norm", "TV norm",
+          "video standard",
+          GST_TYPE_V4L2_TV_NORM, DEFAULT_PROP_TV_NORM,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 GstV4l2Object *
@@ -382,9 +411,6 @@ gst_v4l2_object_destroy (GstV4l2Object * v4l2object)
   if (v4l2object->channel)
     g_free (v4l2object->channel);
 
-  if (v4l2object->norm)
-    g_free (v4l2object->norm);
-
   if (v4l2object->formats) {
     gst_v4l2_object_clear_format_list (v4l2object);
   }
@@ -413,23 +439,10 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
       g_free (v4l2object->videodev);
       v4l2object->videodev = g_value_dup_string (value);
       break;
-#if 0
-    case PROP_NORM:
-      if (GST_V4L2_IS_OPEN (v4l2object)) {
-        GstTuner *tuner = GST_TUNER (v4l2object->element);
-        GstTunerNorm *norm = gst_tuner_find_norm_by_name (tuner,
-            (gchar *) g_value_get_string (value));
-
-        if (norm) {
-          /* like gst_tuner_set_norm (tuner, norm)
-             without g_object_notify */
-          gst_v4l2_tuner_set_norm (v4l2object, norm);
-        }
-      } else {
-        g_free (v4l2object->norm);
-        v4l2object->norm = g_value_dup_string (value);
-      }
+    case PROP_TV_NORM:
+      v4l2object->tv_norm = g_value_get_enum (value);
       break;
+#if 0
     case PROP_CHANNEL:
       if (GST_V4L2_IS_OPEN (v4l2object)) {
         GstTuner *tuner = GST_TUNER (v4l2object->element);
@@ -516,6 +529,9 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
       g_value_set_flags (value, flags);
       break;
     }
+    case PROP_TV_NORM:
+      g_value_set_enum (value, v4l2object->tv_norm);
+      break;
     default:
       return FALSE;
       break;
@@ -535,16 +551,16 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
 
   tuner = GST_TUNER (v4l2object->element);
 
-  if (v4l2object->norm)
-    norm = gst_tuner_find_norm_by_name (tuner, v4l2object->norm);
+  if (v4l2object->tv_norm)
+    norm = gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
   if (norm) {
     gst_tuner_set_norm (tuner, norm);
   } else {
     norm =
         GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2object->element)));
     if (norm) {
-      g_free (v4l2object->norm);
-      v4l2object->norm = g_strdup (norm->label);
+      v4l2object->tv_norm =
+          gst_v4l2_tuner_get_std_id_by_norm (v4l2object, norm);
       gst_tuner_norm_changed (tuner, norm);
     }
   }
@@ -1729,13 +1745,15 @@ default_frame_sizes:
     }
 
     /* Since we can't get framerate directly, try to use the current norm */
-    if (v4l2object->norm && v4l2object->norms) {
+    if (v4l2object->tv_norm && v4l2object->norms) {
       GList *norms;
       GstTunerNorm *norm;
+      GstTunerNorm *current =
+          gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
 
       for (norms = v4l2object->norms; norms != NULL; norms = norms->next) {
         norm = (GstTunerNorm *) norms->data;
-        if (!strcmp (norm->label, v4l2object->norm))
+        if (!strcmp (norm->label, current->label))
           break;
       }
       /* If it's possible, set framerate to that (discrete) value */
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index ba0799f..2b7761e 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -107,7 +107,7 @@ struct _GstV4l2Object {
   GList *channels;
 
   /* properties */
-  gchar *norm;
+  v4l2_std_id tv_norm;
   gchar *channel;
   gulong frequency;
 
@@ -132,7 +132,8 @@ GType gst_v4l2_object_get_type (void);
     PROP_DEVICE,			\
     PROP_DEVICE_NAME,			\
     PROP_DEVICE_FD,			\
-    PROP_FLAGS
+    PROP_FLAGS,         \
+    PROP_TV_NORM
 
 /* create/destroy */
 GstV4l2Object *	gst_v4l2_object_new 		 (GstElement * element,
diff --git a/sys/v4l2/gstv4l2tuner.c b/sys/v4l2/gstv4l2tuner.c
index c5f8442..a805396 100644
--- a/sys/v4l2/gstv4l2tuner.c
+++ b/sys/v4l2/gstv4l2tuner.c
@@ -237,7 +237,6 @@ gst_v4l2_tuner_set_norm (GstV4l2Object * v4l2object, GstTunerNorm * norm)
 GstTunerNorm *
 gst_v4l2_tuner_get_norm (GstV4l2Object * v4l2object)
 {
-  GList *item;
   v4l2_std_id norm;
 
   /* assert that we're opened and that we're using a known item */
@@ -245,6 +244,14 @@ gst_v4l2_tuner_get_norm (GstV4l2Object * v4l2object)
 
   gst_v4l2_get_norm (v4l2object, &norm);
 
+  return gst_v4l2_tuner_get_norm_by_std_id (v4l2object, norm);
+}
+
+GstTunerNorm *
+gst_v4l2_tuner_get_norm_by_std_id (GstV4l2Object * v4l2object, v4l2_std_id norm)
+{
+  GList *item;
+
   for (item = v4l2object->norms; item != NULL; item = item->next) {
     if (norm & GST_V4L2_TUNER_NORM (item->data)->index)
       return (GstTunerNorm *) item->data;
@@ -253,6 +260,20 @@ gst_v4l2_tuner_get_norm (GstV4l2Object * v4l2object)
   return NULL;
 }
 
+v4l2_std_id
+gst_v4l2_tuner_get_std_id_by_norm (GstV4l2Object * v4l2object,
+    GstTunerNorm * norm)
+{
+  GList *item;
+
+  for (item = v4l2object->norms; item != NULL; item = item->next) {
+    if (norm == GST_TUNER_NORM (item->data))
+      return GST_V4L2_TUNER_NORM (item->data)->index;
+  }
+
+  return 0;
+}
+
 void
 gst_v4l2_tuner_set_frequency_and_notify (GstV4l2Object * v4l2object,
     GstTunerChannel * channel, gulong frequency)
diff --git a/sys/v4l2/gstv4l2tuner.h b/sys/v4l2/gstv4l2tuner.h
index 5ec2b67..4c16ac4 100644
--- a/sys/v4l2/gstv4l2tuner.h
+++ b/sys/v4l2/gstv4l2tuner.h
@@ -94,6 +94,11 @@ void              gst_v4l2_tuner_set_norm_and_notify      (GstV4l2Object * v4l2o
 GstTunerNorm*     gst_v4l2_tuner_get_norm                 (GstV4l2Object * v4l2object);
 gboolean          gst_v4l2_tuner_set_norm                 (GstV4l2Object * v4l2object,
 		                                           GstTunerNorm * norm);
+GstTunerNorm*     gst_v4l2_tuner_get_norm_by_std_id       (GstV4l2Object * v4l2object,
+                                               v4l2_std_id norm);
+v4l2_std_id       gst_v4l2_tuner_get_std_id_by_norm       (GstV4l2Object * v4l2object,
+                                               GstTunerNorm * norm);
+
 /* frequency */
 void              gst_v4l2_tuner_set_frequency_and_notify (GstV4l2Object * v4l2object,
                                                            GstTunerChannel * channel, 
-- 
1.6.6





More information about the gstreamer-devel mailing list