mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	v4l2: implement enum_formats with filter
Use the filter to query the device and return a filtered result.
This commit is contained in:
		
							parent
							
								
									8ada6736c0
								
							
						
					
					
						commit
						64ad745437
					
				
					 6 changed files with 302 additions and 44 deletions
				
			
		| 
						 | 
					@ -449,6 +449,8 @@ gst_caps_from_format (SpaFormat *format)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (format->media_subtype == SPA_MEDIA_SUBTYPE_MJPG) {
 | 
					    else if (format->media_subtype == SPA_MEDIA_SUBTYPE_MJPG) {
 | 
				
			||||||
      res = gst_caps_new_simple ("image/jpeg",
 | 
					      res = gst_caps_new_simple ("image/jpeg",
 | 
				
			||||||
 | 
					          "width", G_TYPE_INT, f.info.mjpg.size.width,
 | 
				
			||||||
 | 
					          "height", G_TYPE_INT, f.info.mjpg.size.height,
 | 
				
			||||||
          "framerate", GST_TYPE_FRACTION, f.info.mjpg.framerate.num, f.info.mjpg.framerate.denom,
 | 
					          "framerate", GST_TYPE_FRACTION, f.info.mjpg.framerate.num, f.info.mjpg.framerate.denom,
 | 
				
			||||||
          NULL);
 | 
					          NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,6 +230,7 @@ again:
 | 
				
			||||||
      g_warning ("error output enum formats: %d", res);
 | 
					      g_warning ("error output enum formats: %d", res);
 | 
				
			||||||
      goto error;
 | 
					      goto error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    spa_debug_format (format);
 | 
				
			||||||
    spa_format_fixate (format);
 | 
					    spa_format_fixate (format);
 | 
				
			||||||
  } else if (in_state == SPA_NODE_STATE_CONFIGURE) {
 | 
					  } else if (in_state == SPA_NODE_STATE_CONFIGURE) {
 | 
				
			||||||
    /* only input needs format */
 | 
					    /* only input needs format */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,6 +76,7 @@ typedef void (*SpaNotify) (void *data);
 | 
				
			||||||
#define SPA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
 | 
					#define SPA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
 | 
				
			||||||
#define SPA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
 | 
					#define SPA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SPA_IDX_INVALID  ((unsigned int)-1)
 | 
				
			||||||
#define SPA_ID_INVALID  ((uint32_t)0xffffffff)
 | 
					#define SPA_ID_INVALID  ((uint32_t)0xffffffff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,7 +184,7 @@ spa_props_index_for_id (const SpaProps *props, uint32_t id)
 | 
				
			||||||
     if (props->prop_info[i].id == id)
 | 
					     if (props->prop_info[i].id == id)
 | 
				
			||||||
       return i;
 | 
					       return i;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return -1;
 | 
					  return SPA_IDX_INVALID;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline unsigned int
 | 
					static inline unsigned int
 | 
				
			||||||
| 
						 | 
					@ -196,7 +196,7 @@ spa_props_index_for_name (const SpaProps *props, const char *name)
 | 
				
			||||||
     if (strcmp (props->prop_info[i].name, name) == 0)
 | 
					     if (strcmp (props->prop_info[i].name, name) == 0)
 | 
				
			||||||
       return i;
 | 
					       return i;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return -1;
 | 
					  return SPA_IDX_INVALID;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ static const uint32_t format_values[] = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const SpaPropRangeInfo format_range[] = {
 | 
					static const SpaPropRangeInfo format_range[] = {
 | 
				
			||||||
  { "ENCODED,", "ENCODED", sizeof (uint32_t), &format_values[1] },
 | 
					  { "ENCODED", "ENCODED", sizeof (uint32_t), &format_values[1] },
 | 
				
			||||||
  { "I420", "I420", sizeof (uint32_t), &format_values[2] },
 | 
					  { "I420", "I420", sizeof (uint32_t), &format_values[2] },
 | 
				
			||||||
  { "YV12", "YV12", sizeof (uint32_t), &format_values[3] },
 | 
					  { "YV12", "YV12", sizeof (uint32_t), &format_values[3] },
 | 
				
			||||||
  { "YUY2", "YUY2", sizeof (uint32_t), &format_values[4] },
 | 
					  { "YUY2", "YUY2", sizeof (uint32_t), &format_values[4] },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -297,6 +297,129 @@ find_format_info_by_media_type (SpaMediaType    type,
 | 
				
			||||||
  return NULL;
 | 
					  return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaVideoFormat
 | 
				
			||||||
 | 
					enum_filter_format (const SpaFormat *filter, unsigned int index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SpaVideoFormat video_format = SPA_VIDEO_FORMAT_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((filter->media_type == SPA_MEDIA_TYPE_VIDEO || filter->media_type == SPA_MEDIA_TYPE_IMAGE)) {
 | 
				
			||||||
 | 
					    if (filter->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
 | 
				
			||||||
 | 
					      SpaPropValue val;
 | 
				
			||||||
 | 
					      SpaResult res;
 | 
				
			||||||
 | 
					      unsigned int idx;
 | 
				
			||||||
 | 
					      const SpaPropInfo *pi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FORMAT);
 | 
				
			||||||
 | 
					      if (idx == SPA_IDX_INVALID)
 | 
				
			||||||
 | 
					        return SPA_VIDEO_FORMAT_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pi = &filter->props.prop_info[idx];
 | 
				
			||||||
 | 
					      if (pi->type != SPA_PROP_TYPE_UINT32)
 | 
				
			||||||
 | 
					        return SPA_VIDEO_FORMAT_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      res = spa_props_get_prop (&filter->props, idx, &val);
 | 
				
			||||||
 | 
					      if (res >= 0) {
 | 
				
			||||||
 | 
					        if (index == 0)
 | 
				
			||||||
 | 
					          video_format = *((SpaVideoFormat *)val.value);
 | 
				
			||||||
 | 
					      } else if (res == SPA_RESULT_PROPERTY_UNSET) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (index < pi->n_range_values)
 | 
				
			||||||
 | 
					          video_format = *((SpaVideoFormat *)pi->range_values[index].value);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      if (index == 0)
 | 
				
			||||||
 | 
					        video_format = SPA_VIDEO_FORMAT_ENCODED;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return video_format;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					filter_framesize (struct v4l2_frmsizeenum *frmsize,
 | 
				
			||||||
 | 
					                  const SpaRectangle      *min,
 | 
				
			||||||
 | 
					                  const SpaRectangle      *max,
 | 
				
			||||||
 | 
					                  const SpaRectangle      *step)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (frmsize->type == V4L2_FRMSIZE_TYPE_DISCRETE) {
 | 
				
			||||||
 | 
					    if (frmsize->discrete.width < min->width ||
 | 
				
			||||||
 | 
					        frmsize->discrete.height < min->height ||
 | 
				
			||||||
 | 
					        frmsize->discrete.width > max->width ||
 | 
				
			||||||
 | 
					        frmsize->discrete.height > max->height) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else if (frmsize->type == V4L2_FRMSIZE_TYPE_CONTINUOUS ||
 | 
				
			||||||
 | 
					             frmsize->type == V4L2_FRMSIZE_TYPE_STEPWISE) {
 | 
				
			||||||
 | 
					    /* FIXME, use LCM */
 | 
				
			||||||
 | 
					    frmsize->stepwise.step_width *= step->width;
 | 
				
			||||||
 | 
					    frmsize->stepwise.step_height *= step->height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (frmsize->stepwise.max_width < min->width ||
 | 
				
			||||||
 | 
					        frmsize->stepwise.max_height < min->height ||
 | 
				
			||||||
 | 
					        frmsize->stepwise.min_width > max->width ||
 | 
				
			||||||
 | 
					        frmsize->stepwise.min_height > max->height)
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    frmsize->stepwise.min_width = SPA_MAX (frmsize->stepwise.min_width, min->width);
 | 
				
			||||||
 | 
					    frmsize->stepwise.min_height = SPA_MAX (frmsize->stepwise.min_height, min->height);
 | 
				
			||||||
 | 
					    frmsize->stepwise.max_width = SPA_MIN (frmsize->stepwise.max_width, max->width);
 | 
				
			||||||
 | 
					    frmsize->stepwise.max_height = SPA_MIN (frmsize->stepwise.max_height, max->height);
 | 
				
			||||||
 | 
					  } else
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					compare_fraction (struct v4l2_fract *f1, const SpaFraction *f2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint64_t n1, n2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* fractions are reduced when set, so we can quickly see if they're equal */
 | 
				
			||||||
 | 
					  if (f1->denominator == f2->num && f1->numerator == f2->denom)
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* extend to 64 bits */
 | 
				
			||||||
 | 
					  n1 = ((int64_t) f1->denominator) * f2->denom;
 | 
				
			||||||
 | 
					  n2 = ((int64_t) f1->numerator) * f2->num;
 | 
				
			||||||
 | 
					  if (n1 < n2)
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					filter_framerate (struct v4l2_frmivalenum *frmival,
 | 
				
			||||||
 | 
					                  const SpaFraction       *min,
 | 
				
			||||||
 | 
					                  const SpaFraction       *max,
 | 
				
			||||||
 | 
					                  const SpaFraction       *step)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (frmival->type == V4L2_FRMIVAL_TYPE_DISCRETE) {
 | 
				
			||||||
 | 
					    if (compare_fraction (&frmival->discrete, min) < 0 ||
 | 
				
			||||||
 | 
					        compare_fraction (&frmival->discrete, max) > 0)
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					  } else if (frmival->type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
 | 
				
			||||||
 | 
					             frmival->type == V4L2_FRMIVAL_TYPE_STEPWISE) {
 | 
				
			||||||
 | 
					    /* FIXME, use LCM */
 | 
				
			||||||
 | 
					    frmival->stepwise.step.denominator *= step->num;
 | 
				
			||||||
 | 
					    frmival->stepwise.step.numerator *= step->denom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (compare_fraction (&frmival->stepwise.max, min) < 0 ||
 | 
				
			||||||
 | 
					        compare_fraction (&frmival->stepwise.min, max) > 0)
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (compare_fraction (&frmival->stepwise.min, min) < 0) {
 | 
				
			||||||
 | 
					      frmival->stepwise.min.denominator = min->num;
 | 
				
			||||||
 | 
					      frmival->stepwise.min.numerator = min->denom;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (compare_fraction (&frmival->stepwise.max, max) > 0) {
 | 
				
			||||||
 | 
					      frmival->stepwise.max.denominator = max->num;
 | 
				
			||||||
 | 
					      frmival->stepwise.max.numerator = max->denom;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FOURCC_ARGS(f) (f)&0x7f,((f)>>8)&0x7f,((f)>>16)&0x7f,((f)>>24)&0x7f
 | 
					#define FOURCC_ARGS(f) (f)&0x7f,((f)>>8)&0x7f,((f)>>16)&0x7f,((f)>>24)&0x7f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SpaResult
 | 
					static SpaResult
 | 
				
			||||||
| 
						 | 
					@ -306,7 +429,6 @@ spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, const SpaFormat *
 | 
				
			||||||
  int res, i, pi;
 | 
					  int res, i, pi;
 | 
				
			||||||
  V4l2Format *fmt;
 | 
					  V4l2Format *fmt;
 | 
				
			||||||
  const FormatInfo *info;
 | 
					  const FormatInfo *info;
 | 
				
			||||||
  SpaVideoFormat video_format;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (spa_v4l2_open (this) < 0)
 | 
					  if (spa_v4l2_open (this) < 0)
 | 
				
			||||||
    return SPA_RESULT_ERROR;
 | 
					    return SPA_RESULT_ERROR;
 | 
				
			||||||
| 
						 | 
					@ -324,29 +446,18 @@ spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, const SpaFormat *
 | 
				
			||||||
    *cookie = state;
 | 
					    *cookie = state;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (false) {
 | 
				
			||||||
 | 
					next_fmtdesc:
 | 
				
			||||||
 | 
					    state->fmtdesc.index++;
 | 
				
			||||||
 | 
					    state->next_fmtdesc = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
again:
 | 
					  while (state->next_fmtdesc) {
 | 
				
			||||||
  if (state->next_fmtdesc) {
 | 
					 | 
				
			||||||
    if (filter) {
 | 
					    if (filter) {
 | 
				
			||||||
      SpaPropValue val;
 | 
					      SpaVideoFormat video_format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (state->fmtdesc.index == 1)
 | 
					      video_format = enum_filter_format (filter, state->fmtdesc.index);
 | 
				
			||||||
        return SPA_RESULT_ENUM_END;
 | 
					      if (video_format == SPA_VIDEO_FORMAT_UNKNOWN)
 | 
				
			||||||
 | 
					 | 
				
			||||||
      video_format = SPA_VIDEO_FORMAT_UNKNOWN;
 | 
					 | 
				
			||||||
      if ((filter->media_type == SPA_MEDIA_TYPE_VIDEO)) {
 | 
					 | 
				
			||||||
        if (filter->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
 | 
					 | 
				
			||||||
          if (spa_props_get_prop (&filter->props,
 | 
					 | 
				
			||||||
                                  spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FORMAT),
 | 
					 | 
				
			||||||
                                  &val) >= 0) {
 | 
					 | 
				
			||||||
            video_format = *((SpaVideoFormat *)val.value);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          video_format = SPA_VIDEO_FORMAT_ENCODED;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      } else if ((filter->media_type == SPA_MEDIA_TYPE_IMAGE)) {
 | 
					 | 
				
			||||||
        video_format = SPA_VIDEO_FORMAT_ENCODED;
 | 
					 | 
				
			||||||
      } else
 | 
					 | 
				
			||||||
        return SPA_RESULT_ENUM_END;
 | 
					        return SPA_RESULT_ENUM_END;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      info = find_format_info_by_media_type (filter->media_type,
 | 
					      info = find_format_info_by_media_type (filter->media_type,
 | 
				
			||||||
| 
						 | 
					@ -354,7 +465,7 @@ again:
 | 
				
			||||||
                                             video_format,
 | 
					                                             video_format,
 | 
				
			||||||
                                             0);
 | 
					                                             0);
 | 
				
			||||||
      if (info == NULL)
 | 
					      if (info == NULL)
 | 
				
			||||||
        return SPA_RESULT_ENUM_END;
 | 
					        goto next_fmtdesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      state->fmtdesc.pixelformat = info->fourcc;
 | 
					      state->fmtdesc.pixelformat = info->fourcc;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -370,29 +481,104 @@ again:
 | 
				
			||||||
    state->next_frmsize = true;
 | 
					    state->next_frmsize = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat))) {
 | 
					  if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat)))
 | 
				
			||||||
    state->fmtdesc.index++;
 | 
					    goto next_fmtdesc;
 | 
				
			||||||
    state->next_fmtdesc = true;
 | 
					 | 
				
			||||||
    goto again;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (state->next_frmsize) {
 | 
					next_frmsize:
 | 
				
			||||||
    if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMESIZES, &state->frmsize)) < 0) {
 | 
					  while (state->next_frmsize) {
 | 
				
			||||||
      if (errno == EINVAL) {
 | 
					    if (filter) {
 | 
				
			||||||
        state->fmtdesc.index++;
 | 
					      const SpaPropInfo *pi;
 | 
				
			||||||
        state->next_fmtdesc = true;
 | 
					      unsigned int idx;
 | 
				
			||||||
        goto again;
 | 
					      SpaPropValue val;
 | 
				
			||||||
 | 
					      SpaResult res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* check if we have a fixed frame size */
 | 
				
			||||||
 | 
					      idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE);
 | 
				
			||||||
 | 
					      if (idx == SPA_IDX_INVALID)
 | 
				
			||||||
 | 
					        goto do_frmsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pi = &filter->props.prop_info[idx];
 | 
				
			||||||
 | 
					      if (pi->type != SPA_PROP_TYPE_RECTANGLE)
 | 
				
			||||||
 | 
					        return SPA_RESULT_ENUM_END;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      res = spa_props_get_prop (&filter->props, idx, &val);
 | 
				
			||||||
 | 
					      if (res >= 0) {
 | 
				
			||||||
 | 
					        const SpaRectangle *size = val.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (state->frmsize.index > 0)
 | 
				
			||||||
 | 
					          goto next_fmtdesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state->frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE;
 | 
				
			||||||
 | 
					        state->frmsize.discrete.width = size->width;
 | 
				
			||||||
 | 
					        state->frmsize.discrete.height = size->height;
 | 
				
			||||||
 | 
					        goto have_size;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					do_frmsize:
 | 
				
			||||||
 | 
					    if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMESIZES, &state->frmsize)) < 0) {
 | 
				
			||||||
 | 
					      if (errno == EINVAL)
 | 
				
			||||||
 | 
					        goto next_fmtdesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      perror ("VIDIOC_ENUM_FRAMESIZES");
 | 
					      perror ("VIDIOC_ENUM_FRAMESIZES");
 | 
				
			||||||
      return SPA_RESULT_ENUM_END;
 | 
					      return SPA_RESULT_ENUM_END;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    state->next_frmsize = false;
 | 
					    if (filter) {
 | 
				
			||||||
 | 
					      const SpaPropInfo *pi;
 | 
				
			||||||
 | 
					      unsigned int idx;
 | 
				
			||||||
 | 
					      const SpaRectangle step = { 1, 1 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* check if we have a fixed frame size */
 | 
				
			||||||
 | 
					      idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE);
 | 
				
			||||||
 | 
					      if (idx == SPA_IDX_INVALID)
 | 
				
			||||||
 | 
					        goto have_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* checked above */
 | 
				
			||||||
 | 
					      pi = &filter->props.prop_info[idx];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) {
 | 
				
			||||||
 | 
					        if (filter_framesize (&state->frmsize, pi->range_values[0].value,
 | 
				
			||||||
 | 
					                                               pi->range_values[1].value,
 | 
				
			||||||
 | 
					                                               &step))
 | 
				
			||||||
 | 
					          goto have_size;
 | 
				
			||||||
 | 
					      } else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) {
 | 
				
			||||||
 | 
					        if (filter_framesize (&state->frmsize, pi->range_values[0].value,
 | 
				
			||||||
 | 
					                                               pi->range_values[1].value,
 | 
				
			||||||
 | 
					                                               pi->range_values[2].value))
 | 
				
			||||||
 | 
					          goto have_size;
 | 
				
			||||||
 | 
					      } else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
 | 
				
			||||||
 | 
					        unsigned int i;
 | 
				
			||||||
 | 
					        for (i = 0; i < pi->n_range_values; i++) {
 | 
				
			||||||
 | 
					          if (filter_framesize (&state->frmsize, pi->range_values[i].value,
 | 
				
			||||||
 | 
					                                                 pi->range_values[i].value,
 | 
				
			||||||
 | 
					                                                 &step))
 | 
				
			||||||
 | 
					            goto have_size;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      /* nothing matches the filter, get next frame size */
 | 
				
			||||||
 | 
					      state->frmsize.index++;
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					have_size:
 | 
				
			||||||
    if (state->frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
 | 
					    if (state->frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
 | 
				
			||||||
 | 
					      /* we have a fixed size, use this to get the frame intervals */
 | 
				
			||||||
      state->frmival.index = 0;
 | 
					      state->frmival.index = 0;
 | 
				
			||||||
      state->frmival.pixel_format = state->frmsize.pixel_format;
 | 
					      state->frmival.pixel_format = state->frmsize.pixel_format;
 | 
				
			||||||
      state->frmival.width = state->frmsize.discrete.width;
 | 
					      state->frmival.width = state->frmsize.discrete.width;
 | 
				
			||||||
      state->frmival.height = state->frmsize.discrete.height;
 | 
					      state->frmival.height = state->frmsize.discrete.height;
 | 
				
			||||||
 | 
					      state->next_frmsize = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (state->frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS ||
 | 
				
			||||||
 | 
					             state->frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
 | 
				
			||||||
 | 
					      /* we have a non fixed size, fix to something sensible to get the
 | 
				
			||||||
 | 
					       * framerate */
 | 
				
			||||||
 | 
					      state->frmival.index = 0;
 | 
				
			||||||
 | 
					      state->frmival.pixel_format = state->frmsize.pixel_format;
 | 
				
			||||||
 | 
					      state->frmival.width = state->frmsize.stepwise.min_width;
 | 
				
			||||||
 | 
					      state->frmival.height = state->frmsize.stepwise.min_height;
 | 
				
			||||||
 | 
					      state->next_frmsize = false;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      state->frmsize.index++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -424,7 +610,6 @@ again:
 | 
				
			||||||
  spa_prop_info_fill_video (&fmt->infos[pi],
 | 
					  spa_prop_info_fill_video (&fmt->infos[pi],
 | 
				
			||||||
                            SPA_PROP_ID_VIDEO_FRAMERATE,
 | 
					                            SPA_PROP_ID_VIDEO_FRAMERATE,
 | 
				
			||||||
                            offsetof (V4l2Format, framerate));
 | 
					                            offsetof (V4l2Format, framerate));
 | 
				
			||||||
  fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
 | 
					 | 
				
			||||||
  fmt->infos[pi].range_values = fmt->ranges;
 | 
					  fmt->infos[pi].range_values = fmt->ranges;
 | 
				
			||||||
  fmt->infos[pi].n_range_values = 0;
 | 
					  fmt->infos[pi].n_range_values = 0;
 | 
				
			||||||
  i = state->frmival.index = 0;
 | 
					  i = state->frmival.index = 0;
 | 
				
			||||||
| 
						 | 
					@ -434,20 +619,89 @@ again:
 | 
				
			||||||
      if (errno == EINVAL) {
 | 
					      if (errno == EINVAL) {
 | 
				
			||||||
        state->frmsize.index++;
 | 
					        state->frmsize.index++;
 | 
				
			||||||
        state->next_frmsize = true;
 | 
					        state->next_frmsize = true;
 | 
				
			||||||
 | 
					        if (i == 0)
 | 
				
			||||||
 | 
					          goto next_frmsize;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      perror ("VIDIOC_ENUM_FRAMEINTERVALS");
 | 
					      perror ("VIDIOC_ENUM_FRAMEINTERVALS");
 | 
				
			||||||
      return SPA_RESULT_ENUM_END;
 | 
					      return SPA_RESULT_ENUM_END;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (filter) {
 | 
				
			||||||
 | 
					      SpaPropValue val;
 | 
				
			||||||
 | 
					      const SpaPropInfo *pi;
 | 
				
			||||||
 | 
					      unsigned int idx;
 | 
				
			||||||
 | 
					      SpaResult res;
 | 
				
			||||||
 | 
					      const SpaFraction step = { 1, 1 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* check against filter */
 | 
				
			||||||
 | 
					      idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FRAMERATE);
 | 
				
			||||||
 | 
					      if (idx == SPA_IDX_INVALID)
 | 
				
			||||||
 | 
					        return SPA_RESULT_ENUM_END;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pi = &filter->props.prop_info[idx];
 | 
				
			||||||
 | 
					      if (pi->type != SPA_PROP_TYPE_FRACTION)
 | 
				
			||||||
 | 
					        return SPA_RESULT_ENUM_END;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      res = spa_props_get_prop (&filter->props, idx, &val);
 | 
				
			||||||
 | 
					      if (res == 0) {
 | 
				
			||||||
 | 
					        if (filter_framerate (&state->frmival, val.value,
 | 
				
			||||||
 | 
					                                               val.value,
 | 
				
			||||||
 | 
					                                               &step))
 | 
				
			||||||
 | 
					          goto have_framerate;
 | 
				
			||||||
 | 
					      } else if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) {
 | 
				
			||||||
 | 
					        if (filter_framerate (&state->frmival, pi->range_values[0].value,
 | 
				
			||||||
 | 
					                                               pi->range_values[1].value,
 | 
				
			||||||
 | 
					                                               &step))
 | 
				
			||||||
 | 
					          goto have_framerate;
 | 
				
			||||||
 | 
					      } else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) {
 | 
				
			||||||
 | 
					        if (filter_framerate (&state->frmival, pi->range_values[0].value,
 | 
				
			||||||
 | 
					                                               pi->range_values[1].value,
 | 
				
			||||||
 | 
					                                               pi->range_values[2].value))
 | 
				
			||||||
 | 
					          goto have_framerate;
 | 
				
			||||||
 | 
					      } else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
 | 
				
			||||||
 | 
					        unsigned int i;
 | 
				
			||||||
 | 
					        for (i = 0; i < pi->n_range_values; i++) {
 | 
				
			||||||
 | 
					          if (filter_framerate (&state->frmival, pi->range_values[i].value,
 | 
				
			||||||
 | 
					                                                 pi->range_values[i].value,
 | 
				
			||||||
 | 
					                                                 &step))
 | 
				
			||||||
 | 
					            goto have_framerate;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      state->frmival.index++;
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					have_framerate:
 | 
				
			||||||
    fmt->ranges[i].name = NULL;
 | 
					    fmt->ranges[i].name = NULL;
 | 
				
			||||||
    fmt->ranges[i].description = NULL;
 | 
					    fmt->ranges[i].description = NULL;
 | 
				
			||||||
    fmt->ranges[i].size = sizeof (SpaFraction);
 | 
					    if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
 | 
				
			||||||
    fmt->framerates[i].num = state->frmival.discrete.denominator;
 | 
					      fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
 | 
				
			||||||
    fmt->framerates[i].denom = state->frmival.discrete.numerator;
 | 
					      fmt->ranges[i].size = sizeof (SpaFraction);
 | 
				
			||||||
    fmt->ranges[i].value = &fmt->framerates[i];
 | 
					      fmt->framerates[i].num = state->frmival.discrete.denominator;
 | 
				
			||||||
 | 
					      fmt->framerates[i].denom = state->frmival.discrete.numerator;
 | 
				
			||||||
    i = ++state->frmival.index;
 | 
					      fmt->ranges[i].value = &fmt->framerates[i];
 | 
				
			||||||
 | 
					      i++;
 | 
				
			||||||
 | 
					      state->frmival.index++;
 | 
				
			||||||
 | 
					    } else if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
 | 
				
			||||||
 | 
					               state->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
 | 
				
			||||||
 | 
					      fmt->framerates[0].num = state->frmival.stepwise.min.denominator;
 | 
				
			||||||
 | 
					      fmt->framerates[0].denom = state->frmival.stepwise.min.numerator;
 | 
				
			||||||
 | 
					      fmt->ranges[0].value = &fmt->framerates[0];
 | 
				
			||||||
 | 
					      fmt->framerates[1].num = state->frmival.stepwise.max.denominator;
 | 
				
			||||||
 | 
					      fmt->framerates[1].denom = state->frmival.stepwise.max.numerator;
 | 
				
			||||||
 | 
					      fmt->ranges[1].value = &fmt->framerates[1];
 | 
				
			||||||
 | 
					      if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
 | 
				
			||||||
 | 
					        fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_MIN_MAX;
 | 
				
			||||||
 | 
					        i = 2;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_STEP;
 | 
				
			||||||
 | 
					        fmt->framerates[2].num = state->frmival.stepwise.step.denominator;
 | 
				
			||||||
 | 
					        fmt->framerates[2].denom = state->frmival.stepwise.step.numerator;
 | 
				
			||||||
 | 
					        fmt->ranges[2].value = &fmt->framerates[2];
 | 
				
			||||||
 | 
					        i = 3;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  fmt->infos[pi].n_range_values = i;
 | 
					  fmt->infos[pi].n_range_values = i;
 | 
				
			||||||
  fmt->framerate = fmt->framerates[0];
 | 
					  fmt->framerate = fmt->framerates[0];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue