[media] v4l2-ctrls: compare values only once

When setting a control the control's new value is compared to the current
value twice: once by new_to_cur(), once by cluster_changed(). Not a big
deal when dealing with simple values, but it can be a problem when dealing
with compound types or arrays. So fix this: cluster_changed() sets the
has_changed flag, which is used by new_to_cur() instead of having to do
another compare.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
Hans Verkuil 2014-01-17 08:25:26 -03:00 committed by Mauro Carvalho Chehab
parent 000e4f9a5b
commit 9ea1b7a4b6
2 changed files with 14 additions and 6 deletions

View File

@ -1424,8 +1424,11 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
if (ctrl == NULL)
return;
changed = !ctrl->type_ops->equal(ctrl, ctrl->p_cur, ctrl->p_new);
ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur);
/* has_changed is set by cluster_changed */
changed = ctrl->has_changed;
if (changed)
ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur);
if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
/* Note: CH_FLAGS is only set for auto clusters. */
@ -1462,17 +1465,19 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
value that differs from the current value. */
static int cluster_changed(struct v4l2_ctrl *master)
{
int diff = 0;
bool changed = false;
int i;
for (i = 0; !diff && i < master->ncontrols; i++) {
for (i = 0; i < master->ncontrols; i++) {
struct v4l2_ctrl *ctrl = master->cluster[i];
if (ctrl == NULL)
continue;
diff = !ctrl->type_ops->equal(ctrl, ctrl->p_cur, ctrl->p_new);
ctrl->has_changed = !ctrl->type_ops->equal(ctrl,
ctrl->p_cur, ctrl->p_new);
changed |= ctrl->has_changed;
}
return diff;
return changed;
}
/* Control range checking */

View File

@ -96,6 +96,8 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
* @is_new: Set when the user specified a new value for this control. It
* is also set when called from v4l2_ctrl_handler_setup. Drivers
* should never set this flag.
* @has_changed: Set when the current value differs from the new value. Drivers
* should never use this flag.
* @is_private: If set, then this control is private to its handler and it
* will not be added to any other handlers. Drivers can set
* this flag.
@ -158,6 +160,7 @@ struct v4l2_ctrl {
unsigned int done:1;
unsigned int is_new:1;
unsigned int has_changed:1;
unsigned int is_private:1;
unsigned int is_auto:1;
unsigned int is_int:1;