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) {
 | 
			
		||||
      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,
 | 
			
		||||
          NULL);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -230,6 +230,7 @@ again:
 | 
			
		|||
      g_warning ("error output enum formats: %d", res);
 | 
			
		||||
      goto error;
 | 
			
		||||
    }
 | 
			
		||||
    spa_debug_format (format);
 | 
			
		||||
    spa_format_fixate (format);
 | 
			
		||||
  } else if (in_state == SPA_NODE_STATE_CONFIGURE) {
 | 
			
		||||
    /* 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_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
 | 
			
		||||
 | 
			
		||||
#define SPA_IDX_INVALID  ((unsigned int)-1)
 | 
			
		||||
#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)
 | 
			
		||||
       return i;
 | 
			
		||||
  }
 | 
			
		||||
  return -1;
 | 
			
		||||
  return SPA_IDX_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
       return i;
 | 
			
		||||
  }
 | 
			
		||||
  return -1;
 | 
			
		||||
  return SPA_IDX_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,7 +110,7 @@ static const uint32_t format_values[] = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
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] },
 | 
			
		||||
  { "YV12", "YV12", sizeof (uint32_t), &format_values[3] },
 | 
			
		||||
  { "YUY2", "YUY2", sizeof (uint32_t), &format_values[4] },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -297,6 +297,129 @@ find_format_info_by_media_type (SpaMediaType    type,
 | 
			
		|||
  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
 | 
			
		||||
 | 
			
		||||
static SpaResult
 | 
			
		||||
| 
						 | 
				
			
			@ -306,7 +429,6 @@ spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, const SpaFormat *
 | 
			
		|||
  int res, i, pi;
 | 
			
		||||
  V4l2Format *fmt;
 | 
			
		||||
  const FormatInfo *info;
 | 
			
		||||
  SpaVideoFormat video_format;
 | 
			
		||||
 | 
			
		||||
  if (spa_v4l2_open (this) < 0)
 | 
			
		||||
    return SPA_RESULT_ERROR;
 | 
			
		||||
| 
						 | 
				
			
			@ -324,29 +446,18 @@ spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, const SpaFormat *
 | 
			
		|||
    *cookie = state;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (false) {
 | 
			
		||||
next_fmtdesc:
 | 
			
		||||
    state->fmtdesc.index++;
 | 
			
		||||
    state->next_fmtdesc = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
again:
 | 
			
		||||
  if (state->next_fmtdesc) {
 | 
			
		||||
  while (state->next_fmtdesc) {
 | 
			
		||||
    if (filter) {
 | 
			
		||||
      SpaPropValue val;
 | 
			
		||||
      SpaVideoFormat video_format;
 | 
			
		||||
 | 
			
		||||
      if (state->fmtdesc.index == 1)
 | 
			
		||||
        return SPA_RESULT_ENUM_END;
 | 
			
		||||
 | 
			
		||||
      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
 | 
			
		||||
      video_format = enum_filter_format (filter, state->fmtdesc.index);
 | 
			
		||||
      if (video_format == SPA_VIDEO_FORMAT_UNKNOWN)
 | 
			
		||||
        return SPA_RESULT_ENUM_END;
 | 
			
		||||
 | 
			
		||||
      info = find_format_info_by_media_type (filter->media_type,
 | 
			
		||||
| 
						 | 
				
			
			@ -354,7 +465,7 @@ again:
 | 
			
		|||
                                             video_format,
 | 
			
		||||
                                             0);
 | 
			
		||||
      if (info == NULL)
 | 
			
		||||
        return SPA_RESULT_ENUM_END;
 | 
			
		||||
        goto next_fmtdesc;
 | 
			
		||||
 | 
			
		||||
      state->fmtdesc.pixelformat = info->fourcc;
 | 
			
		||||
    } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -370,29 +481,104 @@ again:
 | 
			
		|||
    state->next_frmsize = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat))) {
 | 
			
		||||
    state->fmtdesc.index++;
 | 
			
		||||
    state->next_fmtdesc = true;
 | 
			
		||||
    goto again;
 | 
			
		||||
  }
 | 
			
		||||
  if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat)))
 | 
			
		||||
    goto next_fmtdesc;
 | 
			
		||||
 | 
			
		||||
  if (state->next_frmsize) {
 | 
			
		||||
    if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMESIZES, &state->frmsize)) < 0) {
 | 
			
		||||
      if (errno == EINVAL) {
 | 
			
		||||
        state->fmtdesc.index++;
 | 
			
		||||
        state->next_fmtdesc = true;
 | 
			
		||||
        goto again;
 | 
			
		||||
next_frmsize:
 | 
			
		||||
  while (state->next_frmsize) {
 | 
			
		||||
    if (filter) {
 | 
			
		||||
      const SpaPropInfo *pi;
 | 
			
		||||
      unsigned int idx;
 | 
			
		||||
      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");
 | 
			
		||||
      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) {
 | 
			
		||||
      /* we have a fixed size, use this to get the frame intervals */
 | 
			
		||||
      state->frmival.index = 0;
 | 
			
		||||
      state->frmival.pixel_format = state->frmsize.pixel_format;
 | 
			
		||||
      state->frmival.width = state->frmsize.discrete.width;
 | 
			
		||||
      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_ID_VIDEO_FRAMERATE,
 | 
			
		||||
                            offsetof (V4l2Format, framerate));
 | 
			
		||||
  fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
 | 
			
		||||
  fmt->infos[pi].range_values = fmt->ranges;
 | 
			
		||||
  fmt->infos[pi].n_range_values = 0;
 | 
			
		||||
  i = state->frmival.index = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -434,20 +619,89 @@ again:
 | 
			
		|||
      if (errno == EINVAL) {
 | 
			
		||||
        state->frmsize.index++;
 | 
			
		||||
        state->next_frmsize = true;
 | 
			
		||||
        if (i == 0)
 | 
			
		||||
          goto next_frmsize;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      perror ("VIDIOC_ENUM_FRAMEINTERVALS");
 | 
			
		||||
      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].description = NULL;
 | 
			
		||||
    if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
 | 
			
		||||
      fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
 | 
			
		||||
      fmt->ranges[i].size = sizeof (SpaFraction);
 | 
			
		||||
      fmt->framerates[i].num = state->frmival.discrete.denominator;
 | 
			
		||||
      fmt->framerates[i].denom = state->frmival.discrete.numerator;
 | 
			
		||||
      fmt->ranges[i].value = &fmt->framerates[i];
 | 
			
		||||
 | 
			
		||||
    i = ++state->frmival.index;
 | 
			
		||||
      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->framerate = fmt->framerates[0];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue