mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
v4l2codecs: enumerate all possible formats
Some decoder may also allow to (down) scale the decoded video. Use VIDIOC_ENUM_FRAMESIZES iotcl to enumerate the possible output formats resolutions. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2589>
This commit is contained in:
parent
85fe9fb61d
commit
d3a01eccae
1 changed files with 80 additions and 25 deletions
|
@ -356,6 +356,79 @@ gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32 pix_fmt,
|
||||||
return TRUE;
|
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 *
|
GstCaps *
|
||||||
gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
|
gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
|
||||||
{
|
{
|
||||||
|
@ -363,10 +436,7 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
|
||||||
struct v4l2_format fmt = {
|
struct v4l2_format fmt = {
|
||||||
.type = self->src_buf_type,
|
.type = self->src_buf_type,
|
||||||
};
|
};
|
||||||
GstVideoFormat format;
|
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GValue list = G_VALUE_INIT;
|
|
||||||
GValue value = G_VALUE_INIT;
|
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
g_return_val_if_fail (self->opened, FALSE);
|
g_return_val_if_fail (self->opened, FALSE);
|
||||||
|
@ -377,20 +447,15 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We first place a structure with the default pixel format */
|
caps =
|
||||||
if (gst_v4l2_format_to_video_format (fmt.fmt.pix_mp.pixelformat, &format))
|
gst_v4l2_decoder_probe_caps_for_format (self,
|
||||||
caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
|
fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
|
||||||
gst_video_format_to_string (format), NULL);
|
|
||||||
else
|
|
||||||
caps = gst_caps_new_empty ();
|
|
||||||
|
|
||||||
/* And then enumerate other possible formats and place that as a second
|
/* And then enumerate other possible formats and place that as a second
|
||||||
* structure in the caps */
|
* structure in the caps */
|
||||||
g_value_init (&list, GST_TYPE_LIST);
|
|
||||||
g_value_init (&value, G_TYPE_STRING);
|
|
||||||
|
|
||||||
for (i = 0; ret >= 0; i++) {
|
for (i = 0; ret >= 0; i++) {
|
||||||
struct v4l2_fmtdesc fmtdesc = { i, self->src_buf_type, };
|
struct v4l2_fmtdesc fmtdesc = { i, self->src_buf_type, };
|
||||||
|
GstCaps *tmp;
|
||||||
|
|
||||||
ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
|
ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -400,19 +465,9 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_v4l2_format_to_video_format (fmtdesc.pixelformat, &format)) {
|
tmp = gst_v4l2_decoder_probe_caps_for_format (self, fmtdesc.pixelformat,
|
||||||
g_value_set_static_string (&value, gst_video_format_to_string (format));
|
fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
|
||||||
gst_value_list_append_value (&list, &value);
|
caps = gst_caps_merge (caps, tmp);
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return caps;
|
return caps;
|
||||||
|
|
Loading…
Reference in a new issue