[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