From 177078ba86f8e1615c2220b96f8c4a8c643c0a6d Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 9 Mar 2014 22:30:09 +0200 Subject: [PATCH] v4l2: implement --v4l2-fps for real (fixes #7395) --- modules/access/v4l2/v4l2.c | 9 +++---- modules/access/v4l2/video.c | 50 +++++++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/modules/access/v4l2/v4l2.c b/modules/access/v4l2/v4l2.c index 20d1fe3890..7807a8af16 100644 --- a/modules/access/v4l2/v4l2.c +++ b/modules/access/v4l2/v4l2.c @@ -67,8 +67,8 @@ #define SIZE_LONGTEXT N_( \ "The specified pixel resolution is forced " \ "(if both width and height are strictly positive)." ) -/*#define FPS_TEXT N_( "Frame rate" ) -#define FPS_LONGTEXT N_( "Maximum frame rate to use (0 = no limits)." )*/ +#define FPS_TEXT N_( "Frame rate" ) +#define FPS_LONGTEXT N_( "Maximum frame rate to use (0 = no limits)." ) #define RADIO_DEVICE_TEXT N_( "Radio device" ) #define RADIO_DEVICE_LONGTEXT N_("Radio tuner device node." ) @@ -310,9 +310,8 @@ vlc_module_begin () add_string( CFG_PREFIX "aspect-ratio", "4:3", ASPECT_TEXT, ASPECT_LONGTEXT, true ) change_safe() - /*add_float( CFG_PREFIX "fps", 0, FPS_TEXT, FPS_LONGTEXT, true )*/ - add_obsolete_float( CFG_PREFIX "fps" ) - change_safe() /* since 2.1.0 */ + add_string( CFG_PREFIX "fps", "60", FPS_TEXT, FPS_LONGTEXT, false ) + change_safe() add_obsolete_bool( CFG_PREFIX "use-libv4l2" ) /* since 2.1.0 */ set_section( N_( "Tuner" ), NULL ) diff --git a/modules/access/v4l2/video.c b/modules/access/v4l2/video.c index c0b24fdcd9..efd3c66805 100644 --- a/modules/access/v4l2/video.c +++ b/modules/access/v4l2/video.c @@ -308,15 +308,19 @@ static int64_t fcmp (const struct v4l2_fract *a, } static const struct v4l2_fract infinity = { 1, 0 }; +static const struct v4l2_fract zero = { 0, 1 }; /** - * Finds the highest frame rate possible of a certain V4L2 format. + * Finds the highest frame rate up to a specific limit possible with a certain + * V4L2 format. * @param fmt V4L2 capture format [IN] + * @param min_it minimum frame internal [IN] * @param it V4L2 frame interval [OUT] * @return 0 on success, -1 on error. */ static int FindMaxRate (vlc_object_t *obj, int fd, const struct v4l2_format *restrict fmt, + const struct v4l2_fract *restrict min_it, struct v4l2_fract *restrict it) { struct v4l2_frmivalenum fie = { @@ -354,7 +358,8 @@ static int FindMaxRate (vlc_object_t *obj, int fd, *it = infinity; do { - if (fcmp (&fie.discrete, it) < 0) + if (fcmp (&fie.discrete, min_it) >= 0 + && fcmp (&fie.discrete, it) < 0) *it = fie.discrete; fie.index++; } @@ -374,7 +379,29 @@ static int FindMaxRate (vlc_object_t *obj, int fd, msg_Dbg (obj, " with %"PRIu32"/%"PRIu32" step", fie.stepwise.step.numerator, fie.stepwise.step.denominator); - *it = fie.stepwise.min; + + if (fcmp (&fie.stepwise.max, min_it) < 0) + { + *it = infinity; + return -1; + } + + if (fcmp (&fie.stepwise.min, min_it) >= 0) + { + *it = fie.stepwise.min; + break; + } + + if (fie.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) + { + *it = *min_it; + break; + } + + it->numerator *= fie.stepwise.step.denominator; + it->denominator *= fie.stepwise.step.denominator; + while (fcmp (it, min_it) < 0) + it->numerator += fie.stepwise.step.numerator; break; } return 0; @@ -407,9 +434,16 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, struct v4l2_frmsizeenum fse = { .pixel_format = fourcc, }; - struct v4l2_fract best_it = infinity; + struct v4l2_fract best_it = infinity, min_it; uint64_t best_area = 0; + if (var_InheritURational(obj, &min_it.denominator, &min_it.numerator, + CFG_PREFIX"fps") == VLC_SUCCESS) + msg_Dbg (obj, " requested frame internal: %"PRIu32"/%"PRIu32, + min_it.numerator, min_it.denominator); + else + min_it = zero; + uint32_t width = var_InheritInteger (obj, CFG_PREFIX"width"); uint32_t height = var_InheritInteger (obj, CFG_PREFIX"height"); if (width > 0 && height > 0) @@ -418,7 +452,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, fmt->fmt.pix.height = height; msg_Dbg (obj, " requested frame size: %"PRIu32"x%"PRIu32, width, height); - FindMaxRate (obj, fd, fmt, &best_it); + FindMaxRate (obj, fd, fmt, &min_it, &best_it); } else if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &fse) < 0) @@ -427,7 +461,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, msg_Dbg (obj, " unknown frame sizes: %s", vlc_strerror_c(errno)); msg_Dbg (obj, " current frame size: %"PRIu32"x%"PRIu32, fmt->fmt.pix.width, fmt->fmt.pix.height); - FindMaxRate (obj, fd, fmt, &best_it); + FindMaxRate (obj, fd, fmt, &min_it, &best_it); } else switch (fse.type) @@ -439,7 +473,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, msg_Dbg (obj, " frame size %"PRIu32"x%"PRIu32, fse.discrete.width, fse.discrete.height); - FindMaxRate (obj, fd, fmt, &cur_it); + FindMaxRate (obj, fd, fmt, &min_it, &cur_it); int64_t c = fcmp (&cur_it, &best_it); uint64_t area = fse.discrete.width * fse.discrete.height; @@ -479,7 +513,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, { struct v4l2_fract cur_it; - FindMaxRate (obj, fd, fmt, &cur_it); + FindMaxRate (obj, fd, fmt, &min_it, &cur_it); int64_t c = fcmp (&cur_it, &best_it); uint64_t area = width * height; -- 2.39.5