return TRUE;
}
+static GstCaps *
+gst_v4l2_decoder_enum_size_for_format (GstV4l2Decoder * self,
+ guint32 pixelformat, gint index, gint unscaled_width, gint unscaled_height)
+{
+ struct v4l2_frmsizeenum size;
+ GstVideoFormat format;
+ gint ret;
+ gboolean res;
+
+ memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
+ size.index = index;
+ size.pixel_format = pixelformat;
+
+ GST_DEBUG_OBJECT (self, "enumerate size index %d for %" GST_FOURCC_FORMAT,
+ index, GST_FOURCC_ARGS (pixelformat));
+
+ ret = ioctl (self->video_fd, VIDIOC_ENUM_FRAMESIZES, &size);
+
+ if (ret < 0)
+ return NULL;
+
+ if (size.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
+ GST_WARNING_OBJECT (self, "V4L2_FRMSIZE type not supported");
+ return NULL;
+ }
+
+ if (gst_util_fraction_compare (unscaled_width, unscaled_height,
+ size.discrete.width, size.discrete.height)) {
+ GST_DEBUG_OBJECT (self,
+ "Pixel ratio modification not supported %dx%d %dx%d (%d)",
+ unscaled_width, unscaled_height, size.discrete.width,
+ size.discrete.height, ret);
+ return NULL;
+ }
+
+ res = gst_v4l2_format_to_video_format (pixelformat, &format);
+ g_assert (res);
+
+ GST_DEBUG_OBJECT (self, "get size (%d x %d) index %d for %" GST_FOURCC_FORMAT,
+ size.discrete.width, size.discrete.height, index,
+ GST_FOURCC_ARGS (pixelformat));
+
+ return gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
+ gst_video_format_to_string (format),
+ "width", G_TYPE_INT, size.discrete.width,
+ "height", G_TYPE_INT, size.discrete.height, NULL);
+}
+
+static GstCaps *
+gst_v4l2_decoder_probe_caps_for_format (GstV4l2Decoder * self,
+ guint32 pixelformat, gint unscaled_width, gint unscaled_height)
+{
+ gint index = 0;
+ GstCaps *caps, *tmp;
+ GstVideoFormat format;
+
+ GST_DEBUG_OBJECT (self, "enumerate size for %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (pixelformat));
+
+ if (!gst_v4l2_format_to_video_format (pixelformat, &format))
+ return gst_caps_new_empty ();
+
+ caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
+ gst_video_format_to_string (format), NULL);
+
+ while ((tmp = gst_v4l2_decoder_enum_size_for_format (self, pixelformat,
+ index++, unscaled_width, unscaled_height))) {
+ caps = gst_caps_merge (caps, tmp);
+ }
+
+ return caps;
+}
+
GstCaps *
gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
{
struct v4l2_format fmt = {
.type = self->src_buf_type,
};
- GstVideoFormat format;
GstCaps *caps;
- GValue list = G_VALUE_INIT;
- GValue value = G_VALUE_INIT;
gint i;
g_return_val_if_fail (self->opened, FALSE);
return FALSE;
}
- /* We first place a structure with the default pixel format */
- if (gst_v4l2_format_to_video_format (fmt.fmt.pix_mp.pixelformat, &format))
- caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
- gst_video_format_to_string (format), NULL);
- else
- caps = gst_caps_new_empty ();
+ caps =
+ gst_v4l2_decoder_probe_caps_for_format (self,
+ fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
/* And then enumerate other possible formats and place that as a second
* structure in the caps */
- g_value_init (&list, GST_TYPE_LIST);
- g_value_init (&value, G_TYPE_STRING);
-
for (i = 0; ret >= 0; i++) {
struct v4l2_fmtdesc fmtdesc = { i, self->src_buf_type, };
+ GstCaps *tmp;
ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
if (ret < 0) {
continue;
}
- if (gst_v4l2_format_to_video_format (fmtdesc.pixelformat, &format)) {
- g_value_set_static_string (&value, gst_video_format_to_string (format));
- gst_value_list_append_value (&list, &value);
- }
- }
- g_value_reset (&value);
-
- if (gst_value_list_get_size (&list) > 0) {
- GstStructure *str = gst_structure_new_empty ("video/x-raw");
- gst_structure_take_value (str, "format", &list);
- gst_caps_append_structure (caps, str);
- } else {
- g_value_reset (&list);
+ tmp = gst_v4l2_decoder_probe_caps_for_format (self, fmtdesc.pixelformat,
+ fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
+ caps = gst_caps_merge (caps, tmp);
}
return caps;