Skip to content
Snippets Groups Projects
Commit 6c8216c6 authored by fryshorts's avatar fryshorts
Browse files

Use helper function to set format in v4l2 input.

Since the helper function also needs to pack/unpack the resolution, the
pack/unpack functions were moved to the helper library and prefixed with
v4l2_ in order to avoid possible collisions.
parent 8d95a7fb
No related branches found
No related tags found
No related merge requests found
......@@ -133,4 +133,39 @@ int_fast32_t v4l2_set_input(int_fast32_t dev, int *input)
: v4l2_ioctl(dev, VIDIOC_S_INPUT, input);
}
int_fast32_t v4l2_set_format(int_fast32_t dev, int *resolution,
int *pixelformat, int *bytesperline)
{
bool set = false;
int width, height;
struct v4l2_format fmt;
if (!dev || !resolution || !pixelformat || !bytesperline)
return -1;
/* We need to set the type in order to query the settings */
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (v4l2_ioctl(dev, VIDIOC_G_FMT, &fmt) < 0)
return -1;
if (*resolution != -1) {
v4l2_unpack_tuple(&width, &height, *resolution);
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
set = true;
}
if (*pixelformat != -1) {
fmt.fmt.pix.pixelformat = *pixelformat;
set = true;
}
if (set && (v4l2_ioctl(dev, VIDIOC_S_FMT, &fmt) < 0))
return -1;
*resolution = v4l2_pack_tuple(fmt.fmt.pix.width, fmt.fmt.pix.height);
*pixelformat = fmt.fmt.pix.pixelformat;
*bytesperline = fmt.fmt.pix.bytesperline;
return 0;
}
......@@ -131,6 +131,38 @@ static const int v4l2_framerates[] =
0
};
/**
* Pack two integer values into one
*
* Obviously the input integers have to be truncated in order to fit into
* one. The effective 16bits left are still enough to handle resolutions and
* framerates just fine.
*
* @param a integer one
* @param b integer two
*
* @return the packed integer
*/
static inline int v4l2_pack_tuple(int a, int b)
{
return (a << 16) | (b & 0xffff);
}
/**
* Unpack two integer values from one
*
* @see v4l2_pack_tuple
*
* @param a pointer to integer a
* @param b pointer to integer b
* @param packed the packed integer
*/
static void v4l2_unpack_tuple(int *a, int *b, int packed)
{
*a = packed >> 16;
*b = packed & 0xffff;
}
/**
* Start the video capture on the device.
*
......@@ -187,6 +219,22 @@ int_fast32_t v4l2_destroy_mmap(struct v4l2_buffer_data *buf);
*/
int_fast32_t v4l2_set_input(int_fast32_t dev, int *input);
/**
* Set the video format on the device.
*
* If the action succeeds resolution, pixelformat and bytesperline are set
* to the used values.
*
* @param dev handle for the v4l2 device
* @param resolution packed value of the resolution or -1 to leave as is
* @param pixelformat index of the pixelformat or -1 to leave as is
* @param bytesperline this will be set accordingly on success
*
* @return negative on failure
*/
int_fast32_t v4l2_set_format(int_fast32_t dev, int *resolution,
int *pixelformat, int *bytesperline);
#ifdef __cplusplus
}
#endif
......@@ -62,36 +62,22 @@ struct v4l2_data {
char *set_device;
int set_input;
int_fast32_t set_pixfmt;
int_fast32_t set_res;
int set_pixfmt;
int set_res;
int_fast32_t set_fps;
/* data used within the capture thread */
int_fast32_t dev;
uint64_t frames;
int_fast32_t width;
int_fast32_t height;
int width;
int height;
int_fast32_t pixfmt;
uint_fast32_t linesize;
int linesize;
struct v4l2_buffer_data buffers;
};
/*
* used to store framerate and resolution values
*/
static int pack_tuple(int a, int b)
{
return (a << 16) | (b & 0xffff);
}
static void unpack_tuple(int *a, int *b, int packed)
{
*a = packed >> 16;
*b = packed & 0xffff;
}
/**
* Prepare the output frame structure for obs and compute plane offsets
*
......@@ -368,7 +354,7 @@ static void v4l2_resolution_list(int dev, uint_fast32_t pixelformat,
dstr_printf(&buffer, "%dx%d", frmsize.discrete.width,
frmsize.discrete.height);
obs_property_list_add_int(prop, buffer.array,
pack_tuple(frmsize.discrete.width,
v4l2_pack_tuple(frmsize.discrete.width,
frmsize.discrete.height));
frmsize.index++;
}
......@@ -380,7 +366,7 @@ static void v4l2_resolution_list(int dev, uint_fast32_t pixelformat,
for (const int *packed = v4l2_framesizes; *packed; ++packed) {
int width;
int height;
unpack_tuple(&width, &height, *packed);
v4l2_unpack_tuple(&width, &height, *packed);
dstr_printf(&buffer, "%dx%d", width, height);
obs_property_list_add_int(prop, buffer.array, *packed);
}
......@@ -414,7 +400,7 @@ static void v4l2_framerate_list(int dev, uint_fast32_t pixelformat,
&frmival) == 0) {
float fps = (float) frmival.discrete.denominator /
frmival.discrete.numerator;
int pack = pack_tuple(frmival.discrete.numerator,
int pack = v4l2_pack_tuple(frmival.discrete.numerator,
frmival.discrete.denominator);
dstr_printf(&buffer, "%.2f", fps);
obs_property_list_add_int(prop, buffer.array, pack);
......@@ -428,7 +414,7 @@ static void v4l2_framerate_list(int dev, uint_fast32_t pixelformat,
for (const int *packed = v4l2_framerates; *packed; ++packed) {
int num;
int denom;
unpack_tuple(&num, &denom, *packed);
v4l2_unpack_tuple(&num, &denom, *packed);
float fps = (float) denom / num;
dstr_printf(&buffer, "%.2f", fps);
obs_property_list_add_int(prop, buffer.array, *packed);
......@@ -511,7 +497,7 @@ static bool resolution_selected(obs_properties_t props, obs_property_t p,
return false;
obs_property_t prop = obs_properties_get(props, "framerate");
unpack_tuple(&width, &height, obs_data_get_int(settings,
v4l2_unpack_tuple(&width, &height, obs_data_get_int(settings,
"resolution"));
v4l2_framerate_list(dev, obs_data_get_int(settings, "pixelformat"),
width, height, prop);
......@@ -596,10 +582,8 @@ static void v4l2_destroy(void *vptr)
*/
static void v4l2_init(struct v4l2_data *data)
{
struct v4l2_format fmt;
struct v4l2_streamparm par;
struct dstr fps;
int width, height;
int fps_num, fps_denom;
blog(LOG_INFO, "Start capture from %s", data->set_device);
......@@ -618,26 +602,19 @@ static void v4l2_init(struct v4l2_data *data)
blog(LOG_INFO, "Input: %d", data->set_input);
/* set pixel format and resolution */
unpack_tuple(&width, &height, data->set_res);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
fmt.fmt.pix.pixelformat = data->set_pixfmt;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (v4l2_ioctl(data->dev, VIDIOC_S_FMT, &fmt) < 0) {
if (v4l2_set_format(data->dev, &data->set_res, &data->set_pixfmt,
&data->linesize) < 0) {
blog(LOG_ERROR, "Unable to set format");
goto fail;
}
data->width = fmt.fmt.pix.width;
data->height = fmt.fmt.pix.height;
data->pixfmt = fmt.fmt.pix.pixelformat;
data->linesize = fmt.fmt.pix.bytesperline;
blog(LOG_INFO, "Resolution: %"PRIuFAST32"x%"PRIuFAST32,
data->width, data->height);
blog(LOG_INFO, "Linesize: %"PRIuFAST32" Bytes", data->linesize);
v4l2_unpack_tuple(&data->width, &data->height, data->set_res);
data->pixfmt = data->set_pixfmt;
blog(LOG_INFO, "Resolution: %dx%d", data->width, data->height);
blog(LOG_INFO, "Pixelformat: %d", data->set_pixfmt);
blog(LOG_INFO, "Linesize: %d Bytes", data->linesize);
/* set framerate */
unpack_tuple(&fps_num, &fps_denom, data->set_fps);
v4l2_unpack_tuple(&fps_num, &fps_denom, data->set_fps);
par.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
par.parm.capture.timeperframe.numerator = fps_num;
par.parm.capture.timeperframe.denominator = fps_denom;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment