0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 13:08:50 +02:00

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.
This commit is contained in:
fryshorts 2014-09-16 00:05:11 +02:00
parent 8d95a7fb47
commit 6c8216c6a6
3 changed files with 101 additions and 41 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;