linux-v4l2: Expand packed values to 4 bytes

These days you might capture card a 175Hz monitor with a framerate
defined as 10000000/57143 that doesnt fit in a short. And reporting a
negative FPS in that case isnt very helpful.
This commit is contained in:
Kurt Kartaltepe 2023-10-02 20:01:07 -07:00 committed by Rodney
parent 5f8eff7ec1
commit 728cd56583
3 changed files with 44 additions and 33 deletions

View file

@ -192,7 +192,7 @@ int_fast32_t v4l2_get_input_caps(int_fast32_t dev, int input, uint32_t *caps)
return 0;
}
int_fast32_t v4l2_set_format(int_fast32_t dev, int *resolution,
int_fast32_t v4l2_set_format(int_fast32_t dev, int64_t *resolution,
int *pixelformat, int *bytesperline)
{
bool set = false;
@ -229,7 +229,7 @@ int_fast32_t v4l2_set_format(int_fast32_t dev, int *resolution,
return 0;
}
int_fast32_t v4l2_set_framerate(int_fast32_t dev, int *framerate)
int_fast32_t v4l2_set_framerate(int_fast32_t dev, int64_t *framerate)
{
bool set = false;
int num, denom;

View file

@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <linux/videodev2.h>
#include <libv4l2.h>
#include <inttypes.h>
#include <obs-module.h>
#include <media-io/video-io.h>
@ -27,6 +28,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
extern "C" {
#endif
#define PACK64(a, b) (((uint64_t)a << 32) | ((uint64_t)b & 0xffffffff))
/**
* Data structure for mapped buffers
*/
@ -91,24 +94,24 @@ static inline enum video_format v4l2_to_obs_video_format(uint_fast32_t format)
* and the height in the low word.
* The array is terminated with a zero.
*/
static const int v4l2_framesizes[] = {
static const int64_t v4l2_framesizes[] = {
/* 4:3 */
160 << 16 | 120, 320 << 16 | 240, 480 << 16 | 320, 640 << 16 | 480,
800 << 16 | 600, 1024 << 16 | 768, 1280 << 16 | 960, 1440 << 16 | 1050,
1440 << 16 | 1080, 1600 << 16 | 1200,
PACK64(160, 120), PACK64(320, 240), PACK64(480, 320), PACK64(640, 480),
PACK64(800, 600), PACK64(1024, 768), PACK64(1280, 960),
PACK64(1440, 1050), PACK64(1440, 1080), PACK64(1600, 1200),
/* 16:9 */
640 << 16 | 360, 960 << 16 | 540, 1280 << 16 | 720, 1600 << 16 | 900,
1920 << 16 | 1080, 1920 << 16 | 1200, 2560 << 16 | 1440,
3840 << 16 | 2160,
PACK64(640, 360), PACK64(960, 540), PACK64(1280, 720),
PACK64(1600, 900), PACK64(1920, 1080), PACK64(1920, 1200),
PACK64(2560, 1440), PACK64(3840, 2160),
/* 21:9 */
2560 << 16 | 1080, 3440 << 16 | 1440, 5120 << 16 | 2160,
PACK64(2560, 1080), PACK64(3440, 1440), PACK64(5120, 2160),
/* tv */
432 << 16 | 520, 480 << 16 | 320, 480 << 16 | 530, 486 << 16 | 440,
576 << 16 | 310, 576 << 16 | 520, 576 << 16 | 570, 720 << 16 | 576,
1024 << 16 | 576,
PACK64(432, 520), PACK64(480, 320), PACK64(480, 530), PACK64(486, 440),
PACK64(576, 310), PACK64(576, 520), PACK64(576, 570), PACK64(720, 576),
PACK64(1024, 576),
0};
@ -119,16 +122,16 @@ static const int v4l2_framesizes[] = {
* word and the denominator in the low word.
* The array is terminated with a zero.
*/
static const int v4l2_framerates[] = {1 << 16 | 60,
1 << 16 | 50,
1 << 16 | 30,
1 << 16 | 25,
1 << 16 | 20,
1 << 16 | 15,
1 << 16 | 10,
1 << 16 | 5,
static const int64_t v4l2_framerates[] = {PACK64(1, 60),
PACK64(1, 50),
PACK64(1, 30),
PACK64(1, 25),
PACK64(1, 20),
PACK64(1, 15),
PACK64(1, 10),
PACK64(1, 5),
0};
0};
/**
* Pack two integer values into one
@ -142,9 +145,9 @@ static const int v4l2_framerates[] = {1 << 16 | 60,
*
* @return the packed integer
*/
static inline int v4l2_pack_tuple(int a, int b)
static inline int64_t v4l2_pack_tuple(int32_t a, int32_t b)
{
return (a << 16) | (b & 0xffff);
return PACK64(a, b);
}
/**
@ -156,10 +159,16 @@ static inline int v4l2_pack_tuple(int a, int b)
* @param b pointer to integer b
* @param packed the packed integer
*/
static void v4l2_unpack_tuple(int *a, int *b, int packed)
static void v4l2_unpack_tuple(int32_t *a, int32_t *b, int64_t packed)
{
*a = packed >> 16;
*b = packed & 0xffff;
// Since we changed from 32 to 64 bits, handle old values too.
if ((packed & 0xffffffff00000000) == 0) {
*a = (int32_t)(packed >> 16);
*b = (int32_t)(packed & 0xffff);
} else {
*a = (int32_t)(packed >> 32);
*b = (int32_t)(packed & 0xffffffff);
}
}
/**
@ -269,7 +278,7 @@ int_fast32_t v4l2_get_input_caps(int_fast32_t dev, int input, uint32_t *caps);
*
* @return negative on failure
*/
int_fast32_t v4l2_set_format(int_fast32_t dev, int *resolution,
int_fast32_t v4l2_set_format(int_fast32_t dev, int64_t *resolution,
int *pixelformat, int *bytesperline);
/**
@ -282,7 +291,7 @@ int_fast32_t v4l2_set_format(int_fast32_t dev, int *resolution,
*
* @return negative on failure
*/
int_fast32_t v4l2_set_framerate(int_fast32_t dev, int *framerate);
int_fast32_t v4l2_set_framerate(int_fast32_t dev, int64_t *framerate);
/**
* Set a video standard on the device.

View file

@ -75,8 +75,8 @@ struct v4l2_data {
int pixfmt;
int standard;
int dv_timing;
int resolution;
int framerate;
int64_t resolution;
int64_t framerate;
int color_range;
/* internal data */
@ -591,7 +591,8 @@ static void v4l2_resolution_list(int dev, uint_fast32_t pixelformat,
blog(LOG_INFO, "Stepwise and Continuous framesizes "
"are currently hardcoded");
for (const int *packed = v4l2_framesizes; *packed; ++packed) {
for (const int64_t *packed = v4l2_framesizes; *packed;
++packed) {
int width;
int height;
v4l2_unpack_tuple(&width, &height, *packed);
@ -643,7 +644,8 @@ static void v4l2_framerate_list(int dev, uint_fast32_t pixelformat,
blog(LOG_INFO, "Stepwise and Continuous framerates "
"are currently hardcoded");
for (const int *packed = v4l2_framerates; *packed; ++packed) {
for (const int64_t *packed = v4l2_framerates; *packed;
++packed) {
int num;
int denom;
v4l2_unpack_tuple(&num, &denom, *packed);