mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -363,10 +436,7 @@ 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);
|
||||
|
@ -377,20 +447,15 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
|
|||
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) {
|
||||
|
@ -400,19 +465,9 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue