v4l2: improve filter with missing format

When the filter has no format property, just enumerate all possible
framerates. Handle error case where the filter has the wrong type.

Makes gst-launch gstpipewiresrc ! video/x-raw ! fakesink work.

See #1793
This commit is contained in:
Wim Taymans 2024-01-17 10:11:29 +01:00
parent 14b265f646
commit 490558f3de

View file

@ -367,11 +367,11 @@ static const struct format_info *find_format_info_by_media_type(uint32_t type,
return NULL; return NULL;
} }
static uint32_t static int
enum_filter_format(uint32_t media_type, int32_t media_subtype, enum_filter_format(uint32_t media_type, int32_t media_subtype,
const struct spa_pod *filter, uint32_t index) const struct spa_pod *filter, uint32_t index)
{ {
uint32_t video_format = 0; uint32_t video_format = SPA_VIDEO_FORMAT_UNKNOWN;
switch (media_type) { switch (media_type) {
case SPA_MEDIA_TYPE_video: case SPA_MEDIA_TYPE_video:
@ -383,12 +383,12 @@ enum_filter_format(uint32_t media_type, int32_t media_subtype,
const uint32_t *values; const uint32_t *values;
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_format))) if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_format)))
return SPA_VIDEO_FORMAT_UNKNOWN; return -ENOENT;
val = spa_pod_get_values(&p->value, &n_values, &choice); val = spa_pod_get_values(&p->value, &n_values, &choice);
if (val->type != SPA_TYPE_Id) if (val->type != SPA_TYPE_Id)
return SPA_VIDEO_FORMAT_UNKNOWN; return -EINVAL;
values = SPA_POD_BODY(val); values = SPA_POD_BODY(val);
@ -503,7 +503,7 @@ spa_v4l2_enum_format(struct impl *this, int seq,
int res, n_fractions; int res, n_fractions;
const struct format_info *info; const struct format_info *info;
struct spa_pod_choice *choice; struct spa_pod_choice *choice;
uint32_t filter_media_type, filter_media_subtype, video_format; uint32_t filter_media_type, filter_media_subtype;
struct spa_v4l2_device *dev = &port->dev; struct spa_v4l2_device *dev = &port->dev;
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder b = { 0 }; struct spa_pod_builder b = { 0 };
@ -545,16 +545,19 @@ spa_v4l2_enum_format(struct impl *this, int seq,
if (filter) { if (filter) {
struct v4l2_format fmt; struct v4l2_format fmt;
video_format = enum_filter_format(filter_media_type, res = enum_filter_format(filter_media_type,
filter_media_subtype, filter_media_subtype,
filter, port->fmtdesc.index); filter, port->fmtdesc.index);
if (res == -ENOENT)
if (video_format == SPA_VIDEO_FORMAT_UNKNOWN) goto do_enum_fmt;
if (res < 0)
goto exit;
if (res == SPA_VIDEO_FORMAT_UNKNOWN)
goto enum_end; goto enum_end;
info = find_format_info_by_media_type(filter_media_type, info = find_format_info_by_media_type(filter_media_type,
filter_media_subtype, filter_media_subtype,
video_format, 0); res, 0);
if (info == NULL) if (info == NULL)
goto next_fmtdesc; goto next_fmtdesc;
@ -580,6 +583,7 @@ spa_v4l2_enum_format(struct impl *this, int seq,
} }
} else { } else {
do_enum_fmt:
if ((res = xioctl(dev->fd, VIDIOC_ENUM_FMT, &port->fmtdesc)) < 0) { if ((res = xioctl(dev->fd, VIDIOC_ENUM_FMT, &port->fmtdesc)) < 0) {
if (errno == EINVAL) if (errno == EINVAL)
goto enum_end; goto enum_end;