sys/v4l2/v4l2src_calls.c: Fix framerate detection code some more.

Original commit message from CVS:
* sys/v4l2/v4l2src_calls.c:
(gst_v4l2src_probe_caps_for_format_and_size):
Fix framerate detection code some more.
Handle the case where there is a weird step in the stepwise framerates.
Don't overwrite the min interval with the framerate, use a temp variable
instead.
Use max in the Continuous framerate intervals instead of step, which is
1 according to the docs. Fixes #475424.
This commit is contained in:
Wim Taymans 2007-09-11 15:37:55 +00:00
parent 4b25ca6267
commit 3b78ab50ef
2 changed files with 73 additions and 40 deletions

View file

@ -1,3 +1,14 @@
2007-09-11 Wim Taymans <wim.taymans@gmail.com>
* sys/v4l2/v4l2src_calls.c:
(gst_v4l2src_probe_caps_for_format_and_size):
Fix framerate detection code some more.
Handle the case where there is a weird step in the stepwise framerates.
Don't overwrite the min interval with the framerate, use a temp variable
instead.
Use max in the Continuous framerate intervals instead of step, which is
1 according to the docs. Fixes #475424.
2007-09-10 Wim Taymans <wim.taymans@gmail.com> 2007-09-10 Wim Taymans <wim.taymans@gmail.com>
* gst/udp/gstudpsrc.c: (gst_udpsrc_init), (gst_udpsrc_create): * gst/udp/gstudpsrc.c: (gst_udpsrc_init), (gst_udpsrc_create):

View file

@ -452,7 +452,7 @@ gst_v4l2src_probe_caps_for_format_and_size (GstV4l2Src * v4l2src,
struct v4l2_frmivalenum ival; struct v4l2_frmivalenum ival;
guint32 num, denom; guint32 num, denom;
GstStructure *s; GstStructure *s;
GValue rate = { 0, }; GValue rates = { 0, };
ret = gst_caps_new_empty (); ret = gst_caps_new_empty ();
@ -471,10 +471,10 @@ gst_v4l2src_probe_caps_for_format_and_size (GstV4l2Src * v4l2src,
goto enum_frameintervals_failed; goto enum_frameintervals_failed;
if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
GValue frac = { 0, }; GValue rate = { 0, };
g_value_init (&rate, GST_TYPE_LIST); g_value_init (&rates, GST_TYPE_LIST);
g_value_init (&frac, GST_TYPE_FRACTION); g_value_init (&rate, GST_TYPE_FRACTION);
do { do {
num = ival.discrete.numerator; num = ival.discrete.numerator;
@ -488,65 +488,85 @@ gst_v4l2src_probe_caps_for_format_and_size (GstV4l2Src * v4l2src,
GST_LOG_OBJECT (v4l2src, "adding discrete framerate: %d/%d", denom, num); GST_LOG_OBJECT (v4l2src, "adding discrete framerate: %d/%d", denom, num);
gst_value_set_fraction (&frac, denom, num); /* swap to get the framerate */
gst_value_list_append_value (&rate, &frac); gst_value_set_fraction (&rate, denom, num);
gst_value_list_append_value (&rates, &rate);
ival.index++; ival.index++;
} while (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0); } while (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
} else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
GValue frac = { 0, }; GValue min = { 0, };
GValue step = { 0, }; GValue step = { 0, };
GValue max = { 0, }; GValue max = { 0, };
gboolean added = FALSE; gboolean added = FALSE;
guint32 minnum, mindenom;
guint32 maxnum, maxdenom;
g_value_init (&rate, GST_TYPE_LIST); g_value_init (&rates, GST_TYPE_LIST);
g_value_init (&frac, GST_TYPE_FRACTION); g_value_init (&min, GST_TYPE_FRACTION);
g_value_init (&step, GST_TYPE_FRACTION); g_value_init (&step, GST_TYPE_FRACTION);
g_value_init (&max, GST_TYPE_FRACTION); g_value_init (&max, GST_TYPE_FRACTION);
num = ival.stepwise.min.numerator; /* get the min */
denom = ival.stepwise.min.denominator; minnum = ival.stepwise.min.numerator;
if (num > G_MAXINT || denom > G_MAXINT) { mindenom = ival.stepwise.min.denominator;
num >>= 1; if (minnum > G_MAXINT || mindenom > G_MAXINT) {
denom >>= 1; minnum >>= 1;
mindenom >>= 1;
} }
GST_LOG_OBJECT (v4l2src, "stepwise min frame interval: %d/%d", num, denom); GST_LOG_OBJECT (v4l2src, "stepwise min frame interval: %d/%d", minnum,
gst_value_set_fraction (&frac, num, denom); mindenom);
gst_value_set_fraction (&min, minnum, mindenom);
/* get the max */
maxnum = ival.stepwise.max.numerator;
maxdenom = ival.stepwise.max.denominator;
if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
maxnum >>= 1;
maxdenom >>= 1;
}
GST_LOG_OBJECT (v4l2src, "stepwise max frame interval: %d/%d", maxnum,
maxdenom);
gst_value_set_fraction (&max, maxnum, maxdenom);
/* get the step */
num = ival.stepwise.step.numerator; num = ival.stepwise.step.numerator;
denom = ival.stepwise.step.denominator; denom = ival.stepwise.step.denominator;
if (num > G_MAXINT || denom > G_MAXINT) { if (num > G_MAXINT || denom > G_MAXINT) {
num >>= 1; num >>= 1;
denom >>= 1; denom >>= 1;
} }
if (num == 0 || denom == 0) {
/* in this case we have a wrong fraction or no step, set the step to max
* so that we only add the min value in the loop below */
num = maxnum;
denom = maxdenom;
}
/* since we only have gst_value_fraction_subtract and not add, negate the /* since we only have gst_value_fraction_subtract and not add, negate the
numerator */ * numerator */
GST_LOG_OBJECT (v4l2src, "stepwise step frame interval: %d/%d", num, denom); GST_LOG_OBJECT (v4l2src, "stepwise step frame interval: %d/%d", num, denom);
gst_value_set_fraction (&step, -num, denom); gst_value_set_fraction (&step, -num, denom);
num = ival.stepwise.max.numerator; while (gst_value_compare (&min, &max) <= 0) {
denom = ival.stepwise.max.denominator; GValue rate = { 0, };
if (num > G_MAXINT || denom > G_MAXINT) {
num >>= 1;
denom >>= 1;
}
GST_LOG_OBJECT (v4l2src, "stepwise max frame interval: %d/%d", num, denom);
gst_value_set_fraction (&max, num, denom);
while (gst_value_compare (&frac, &max) <= 0) { num = gst_value_get_fraction_numerator (&min);
num = gst_value_get_fraction_numerator (&frac); denom = gst_value_get_fraction_denominator (&min);
denom = gst_value_get_fraction_denominator (&frac);
GST_LOG_OBJECT (v4l2src, "adding stepwise framerate: %d/%d", denom, num); GST_LOG_OBJECT (v4l2src, "adding stepwise framerate: %d/%d", denom, num);
/* invert to get the framerate */ /* invert to get the framerate */
gst_value_set_fraction (&frac, denom, num); g_value_init (&rate, GST_TYPE_FRACTION);
gst_value_list_append_value (&rate, &frac); gst_value_set_fraction (&rate, denom, num);
gst_value_list_append_value (&rates, &rate);
added = TRUE; added = TRUE;
/* we're actually adding because step was negated above. This is because /* we're actually adding because step was negated above. This is because
* there is no _add function... */ * there is no _add function... */
if (!gst_value_fraction_subtract (&frac, &frac, &step)) { if (!gst_value_fraction_subtract (&min, &min, &step)) {
GST_WARNING_OBJECT (v4l2src, "could not step fraction!"); GST_WARNING_OBJECT (v4l2src, "could not step fraction!");
break; break;
} }
@ -554,13 +574,14 @@ gst_v4l2src_probe_caps_for_format_and_size (GstV4l2Src * v4l2src,
if (!added) { if (!added) {
/* no range was added, make a default range */ /* no range was added, make a default range */
GST_WARNING_OBJECT (v4l2src, "no range added, setting 0/1 to 100/1"); GST_WARNING_OBJECT (v4l2src, "no range added, setting 0/1 to 100/1");
g_value_init (&rate, GST_TYPE_FRACTION_RANGE); g_value_unset (&rates);
gst_value_set_fraction_range_full (&rate, 0, 1, 100, 1); g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&rates, 0, 1, 100, 1);
} }
} else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
guint32 maxnum, maxdenom; guint32 maxnum, maxdenom;
g_value_init (&rate, GST_TYPE_FRACTION_RANGE); g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
num = ival.stepwise.min.numerator; num = ival.stepwise.min.numerator;
denom = ival.stepwise.min.denominator; denom = ival.stepwise.min.denominator;
@ -569,9 +590,8 @@ gst_v4l2src_probe_caps_for_format_and_size (GstV4l2Src * v4l2src,
denom >>= 1; denom >>= 1;
} }
/* FIXME? doesn't it make more sense to have min and max as the range? */ maxnum = ival.stepwise.max.numerator;
maxnum = ival.stepwise.step.numerator; maxdenom = ival.stepwise.max.denominator;
maxdenom = ival.stepwise.step.denominator;
if (maxnum > G_MAXINT || maxdenom > G_MAXINT) { if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
maxnum >>= 1; maxnum >>= 1;
maxdenom >>= 1; maxdenom >>= 1;
@ -580,7 +600,7 @@ gst_v4l2src_probe_caps_for_format_and_size (GstV4l2Src * v4l2src,
GST_LOG_OBJECT (v4l2src, "continuous frame interval %d/%d to %d/%d", GST_LOG_OBJECT (v4l2src, "continuous frame interval %d/%d to %d/%d",
maxdenom, maxnum, denom, num); maxdenom, maxnum, denom, num);
gst_value_set_fraction_range_full (&rate, maxdenom, maxnum, denom, num); gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
} else { } else {
goto unknown_type; goto unknown_type;
} }
@ -588,10 +608,12 @@ gst_v4l2src_probe_caps_for_format_and_size (GstV4l2Src * v4l2src,
s = gst_structure_copy (template); s = gst_structure_copy (template);
gst_structure_set (s, "width", G_TYPE_INT, (gint) width, gst_structure_set (s, "width", G_TYPE_INT, (gint) width,
"height", G_TYPE_INT, (gint) height, NULL); "height", G_TYPE_INT, (gint) height, NULL);
gst_structure_set_value (s, "framerate", &rate); gst_structure_set_value (s, "framerate", &rates);
g_value_unset (&rate); g_value_unset (&rates);
return s; return s;
/* ERRORS */
enum_frameintervals_failed: enum_frameintervals_failed:
{ {
GST_DEBUG_OBJECT (v4l2src, GST_DEBUG_OBJECT (v4l2src,