Message ID | 20190417114135.5987-1-ricardo@ribalda.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2,1/2] libv4lconvert: Port supported_src_formats to bit-ops | expand |
Hi, On 17-04-19 13:41, Ricardo Ribalda Delgado wrote: > We have passed the barrier of 64 supported formats, therefore a int64_t > is not enough for holding the bitfield. > > Instead use bit-ops ala kernel. > > Signed-off-by: Ricardo Ribalda Delgado <ricardo@ribalda.com> > Suggested-by: Hans de Goede <hdegoede@redhat.com> Thank you. I've dropped the unnecessary __prefix from the bitop functions and I've pushed both patches to the upstream master branch now. Regards, Hans > --- > lib/libv4lconvert/libv4lconvert-priv.h | 3 +- > lib/libv4lconvert/libv4lconvert.c | 40 ++++++++++++++++++++++---- > 2 files changed, 37 insertions(+), 6 deletions(-) > > diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h > index a8046ce2..5286a9b1 100644 > --- a/lib/libv4lconvert/libv4lconvert-priv.h > +++ b/lib/libv4lconvert/libv4lconvert-priv.h > @@ -38,6 +38,7 @@ > #include "tinyjpeg.h" > > #define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0])) > +#define BITS_PER_LONG (8 * sizeof(long)) > > #define V4LCONVERT_ERROR_MSG_SIZE 256 > #define V4LCONVERT_MAX_FRAMESIZES 256 > @@ -55,7 +56,7 @@ struct v4lconvert_data { > int flags; /* bitfield */ > int control_flags; /* bitfield */ > unsigned int no_formats; > - int64_t supported_src_formats; /* bitfield */ > + unsigned long supported_src_formats[128 / BITS_PER_LONG]; > char error_msg[V4LCONVERT_ERROR_MSG_SIZE]; > struct jdec_private *tinyjpeg; > #ifdef HAVE_JPEG > diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c > index 78fb3432..0607cc8b 100644 > --- a/lib/libv4lconvert/libv4lconvert.c > +++ b/lib/libv4lconvert/libv4lconvert.c > @@ -32,6 +32,29 @@ > #include "libv4lsyscall-priv.h" > > #define MIN(a, b) (((a) < (b)) ? (a) : (b)) > +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) > +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) > + > +static inline void __set_bit(int nr, volatile unsigned long *addr) > +{ > + unsigned long mask = BIT_MASK(nr); > + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); > + > + *p |= mask; > +} > + > +static inline void __clear_bit(int nr, volatile unsigned long *addr) > +{ > + unsigned long mask = BIT_MASK(nr); > + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); > + > + *p &= ~mask; > +} > + > +static inline int __test_bit(int nr, const volatile unsigned long *addr) > +{ > + return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); > +} > > static void *dev_init(int fd) > { > @@ -231,7 +254,7 @@ struct v4lconvert_data *v4lconvert_create_with_dev_ops(int fd, void *dev_ops_pri > break; > > if (j < ARRAY_SIZE(supported_src_pixfmts)) { > - data->supported_src_formats |= 1ULL << j; > + __set_bit(j, data->supported_src_formats); > v4lconvert_get_framesizes(data, fmt.pixelformat, j); > if (!supported_src_pixfmts[j].needs_conversion) > always_needs_conversion = 0; > @@ -316,8 +339,15 @@ int v4lconvert_supported_dst_format(unsigned int pixelformat) > > int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data) > { > - return v4lcontrol_needs_conversion(data->control) && > - data->supported_src_formats; > + int i; > + > + for (i = 0 ; i < ARRAY_SIZE(data->supported_src_formats); i++) > + if (data->supported_src_formats[i]) > + break; > + if (i == ARRAY_SIZE(data->supported_src_formats)) > + return 0; > + > + return v4lcontrol_needs_conversion(data->control); > } > > /* See libv4lconvert.h for description of in / out parameters */ > @@ -334,7 +364,7 @@ int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt) > > for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) > if (v4lconvert_supported_dst_fmt_only(data) || > - !(data->supported_src_formats & (1ULL << i))) { > + !__test_bit(i, data->supported_src_formats)) { > faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt; > no_faked_fmts++; > } > @@ -490,7 +520,7 @@ static int v4lconvert_do_try_format(struct v4lconvert_data *data, > > for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) { > /* is this format supported? */ > - if (!(data->supported_src_formats & (1ULL << i))) > + if (!__test_bit(i, data->supported_src_formats)) > continue; > > try_fmt = *dest_fmt; >
diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h index a8046ce2..5286a9b1 100644 --- a/lib/libv4lconvert/libv4lconvert-priv.h +++ b/lib/libv4lconvert/libv4lconvert-priv.h @@ -38,6 +38,7 @@ #include "tinyjpeg.h" #define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0])) +#define BITS_PER_LONG (8 * sizeof(long)) #define V4LCONVERT_ERROR_MSG_SIZE 256 #define V4LCONVERT_MAX_FRAMESIZES 256 @@ -55,7 +56,7 @@ struct v4lconvert_data { int flags; /* bitfield */ int control_flags; /* bitfield */ unsigned int no_formats; - int64_t supported_src_formats; /* bitfield */ + unsigned long supported_src_formats[128 / BITS_PER_LONG]; char error_msg[V4LCONVERT_ERROR_MSG_SIZE]; struct jdec_private *tinyjpeg; #ifdef HAVE_JPEG diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c index 78fb3432..0607cc8b 100644 --- a/lib/libv4lconvert/libv4lconvert.c +++ b/lib/libv4lconvert/libv4lconvert.c @@ -32,6 +32,29 @@ #include "libv4lsyscall-priv.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) + +static inline void __set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p |= mask; +} + +static inline void __clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p &= ~mask; +} + +static inline int __test_bit(int nr, const volatile unsigned long *addr) +{ + return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); +} static void *dev_init(int fd) { @@ -231,7 +254,7 @@ struct v4lconvert_data *v4lconvert_create_with_dev_ops(int fd, void *dev_ops_pri break; if (j < ARRAY_SIZE(supported_src_pixfmts)) { - data->supported_src_formats |= 1ULL << j; + __set_bit(j, data->supported_src_formats); v4lconvert_get_framesizes(data, fmt.pixelformat, j); if (!supported_src_pixfmts[j].needs_conversion) always_needs_conversion = 0; @@ -316,8 +339,15 @@ int v4lconvert_supported_dst_format(unsigned int pixelformat) int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data) { - return v4lcontrol_needs_conversion(data->control) && - data->supported_src_formats; + int i; + + for (i = 0 ; i < ARRAY_SIZE(data->supported_src_formats); i++) + if (data->supported_src_formats[i]) + break; + if (i == ARRAY_SIZE(data->supported_src_formats)) + return 0; + + return v4lcontrol_needs_conversion(data->control); } /* See libv4lconvert.h for description of in / out parameters */ @@ -334,7 +364,7 @@ int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt) for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) if (v4lconvert_supported_dst_fmt_only(data) || - !(data->supported_src_formats & (1ULL << i))) { + !__test_bit(i, data->supported_src_formats)) { faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt; no_faked_fmts++; } @@ -490,7 +520,7 @@ static int v4lconvert_do_try_format(struct v4lconvert_data *data, for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) { /* is this format supported? */ - if (!(data->supported_src_formats & (1ULL << i))) + if (!__test_bit(i, data->supported_src_formats)) continue; try_fmt = *dest_fmt;
We have passed the barrier of 64 supported formats, therefore a int64_t is not enough for holding the bitfield. Instead use bit-ops ala kernel. Signed-off-by: Ricardo Ribalda Delgado <ricardo@ribalda.com> Suggested-by: Hans de Goede <hdegoede@redhat.com> --- lib/libv4lconvert/libv4lconvert-priv.h | 3 +- lib/libv4lconvert/libv4lconvert.c | 40 ++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-)