v4l2: improve pixel aspect ratio handling

Instead of just assuming a aspect ratio of 1/1 use VIDIOC_CROPCAP to ask
the device.
This also add a pixel-aspect-ratio property to overwrite the value from the
driver and a force-aspect-ratio property to ignore it.

https://bugzilla.gnome.org/show_bug.cgi?id=700285
This commit is contained in:
Michael Olbrich 2013-06-04 08:26:33 +02:00 committed by Sebastian Dröge
parent 86405d6ee7
commit 74d217c44b
2 changed files with 96 additions and 5 deletions

View file

@ -504,6 +504,33 @@ gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class,
g_param_spec_boxed ("extra-controls", "Extra Controls",
"Extra v4l2 controls (CIDs) for the device",
GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstV4l2Src:pixel-aspect-ratio
*
* The pixel aspect ratio of the device. This overwrites the pixel aspect
* ratio queried from the device.
*
* Since: 1.2
*/
g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
"Overwrite the pixel aspect ratio of the device", "1/1",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstV4l2Src:force-aspect-ratio
*
* When enabled, the pixel aspect ratio queried from the device or set
* with the pixel-aspect-ratio property will be enforced.
*
* Since: 1.2
*/
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
"When enabled, the pixel aspect ratio will be enforced", TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
GstV4l2Object *
@ -540,6 +567,8 @@ gst_v4l2_object_new (GstElement * element,
v4l2object->xwindow_id = 0;
v4l2object->keep_aspect = TRUE;
return v4l2object;
}
@ -679,6 +708,21 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
gst_v4l2_set_controls (v4l2object, v4l2object->extra_controls);
break;
}
case PROP_PIXEL_ASPECT_RATIO:
g_free (v4l2object->par);
v4l2object->par = g_new0 (GValue, 1);
g_value_init (v4l2object->par, GST_TYPE_FRACTION);
if (!g_value_transform (value, v4l2object->par)) {
g_warning ("Could not transform string to aspect ratio");
gst_value_set_fraction (v4l2object->par, 1, 1);
}
GST_DEBUG_OBJECT (v4l2object->element, "set PAR to %d/%d",
gst_value_get_fraction_numerator (v4l2object->par),
gst_value_get_fraction_denominator (v4l2object->par));
break;
case PROP_FORCE_ASPECT_RATIO:
v4l2object->keep_aspect = g_value_get_boolean (value);
break;
default:
return FALSE;
break;
@ -758,6 +802,13 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
case PROP_EXTRA_CONTROLS:
gst_value_set_structure (value, v4l2object->extra_controls);
break;
case PROP_PIXEL_ASPECT_RATIO:
if (v4l2object->par)
g_value_transform (v4l2object->par, value);
break;
case PROP_FORCE_ASPECT_RATIO:
g_value_set_boolean (value, v4l2object->keep_aspect);
break;
default:
return FALSE;
break;
@ -1625,6 +1676,43 @@ static gboolean
gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
guint32 pixelformat, gint * width, gint * height, gboolean * interlaced);
static void
gst_v4l2_object_add_aspect_ratio (GstV4l2Object * v4l2object, GstStructure * s)
{
struct v4l2_cropcap cropcap;
int num = 1, den = 1;
if (!v4l2object->keep_aspect)
return;
if (v4l2object->par) {
num = gst_value_get_fraction_numerator (v4l2object->par);
den = gst_value_get_fraction_denominator (v4l2object->par);
goto done;
}
memset (&cropcap, 0, sizeof (cropcap));
cropcap.type = v4l2object->type;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0)
goto cropcap_failed;
num = cropcap.pixelaspect.numerator;
den = cropcap.pixelaspect.denominator;
done:
gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, num, den,
NULL);
return;
cropcap_failed:
if (errno != ENOTTY)
GST_WARNING_OBJECT (v4l2object->element,
"Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s",
g_strerror (errno));
goto done;
}
/* The frame interval enumeration code first appeared in Linux 2.6.19. */
#ifdef VIDIOC_ENUM_FRAMEINTERVALS
@ -1811,8 +1899,8 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
return_data:
s = gst_structure_copy (template);
gst_structure_set (s, "width", G_TYPE_INT, (gint) width,
"height", G_TYPE_INT, (gint) height,
"pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
"height", G_TYPE_INT, (gint) height, NULL);
gst_v4l2_object_add_aspect_ratio (v4l2object, s);
if (g_str_equal (gst_structure_get_name (s), "video/x-raw"))
gst_structure_set (s, "interlace-mode", G_TYPE_STRING,
(interlaced ? "mixed" : "progressive"), NULL);
@ -2078,8 +2166,7 @@ default_frame_sizes:
if (g_str_equal (gst_structure_get_name (tmp), "video/x-raw"))
gst_structure_set (tmp, "interlace-mode", G_TYPE_STRING,
(interlaced ? "mixed" : "progressive"), NULL);
gst_structure_set (tmp, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
NULL);
gst_v4l2_object_add_aspect_ratio (v4l2object, tmp);
gst_caps_append_structure (ret, tmp);

View file

@ -150,6 +150,8 @@ struct _GstV4l2Object {
gchar *channel;
gulong frequency;
GstStructure *extra_controls;
gboolean keep_aspect;
GValue *par;
/* X-overlay */
GstV4l2Xv *xv;
@ -179,7 +181,9 @@ GType gst_v4l2_object_get_type (void);
PROP_HUE, \
PROP_TV_NORM, \
PROP_IO_MODE, \
PROP_EXTRA_CONTROLS
PROP_EXTRA_CONTROLS, \
PROP_PIXEL_ASPECT_RATIO, \
PROP_FORCE_ASPECT_RATIO
/* create/destroy */
GstV4l2Object * gst_v4l2_object_new (GstElement * element,