提交 d7ec87ff 编写于 作者: P Piotr Esden-Tempski 提交者: Jim

linux-v4l2: Add auto reset on timeout option

Adds frame time multiple based timeout option, instead of the hardcoded
1 second timeout.

Adds optional automatic device stream reset when the device times out.
Helps with devices that "lock up" or "freeze", for example Magewell and
Elgato USB HDMI capture devices.

The automatic reset is by default off and optional. Turning it on can
cause issues for devices that work but drop a lot of frames.
上级 552bd035
......@@ -13,3 +13,5 @@ ColorRange.Default="Default"
ColorRange.Partial="Partial"
ColorRange.Full="Full"
CameraCtrls="Camera Controls"
AutoresetOnTimeout="Autoreset on Timeout"
FramesUntilTimeout="Frames Until Timeout"
......@@ -61,6 +61,17 @@ int_fast32_t v4l2_stop_capture(int_fast32_t dev)
return 0;
}
int_fast32_t v4l2_reset_capture(int_fast32_t dev, struct v4l2_buffer_data *buf)
{
blog(LOG_DEBUG, "attempting to reset capture");
if (v4l2_stop_capture(dev) < 0)
return -1;
if (v4l2_start_capture(dev, buf) < 0)
return -1;
return 0;
}
#ifdef _DEBUG
int_fast32_t v4l2_query_all_buffers(int_fast32_t dev,
struct v4l2_buffer_data *buf_data)
......
......@@ -184,6 +184,20 @@ int_fast32_t v4l2_start_capture(int_fast32_t dev, struct v4l2_buffer_data *buf);
*/
int_fast32_t v4l2_stop_capture(int_fast32_t dev);
/**
* Resets video capture on the device.
*
* This runs stop and start capture again. Stop dequeues the buffers and start
* enqueues the memory mapped buffers and instructs the device to start
* the video stream.
*
* @param dev handle for the v4l2 device
* @param buf buffer data
*
* @return negative on failure
*/
int_fast32_t v4l2_reset_capture(int_fast32_t dev, struct v4l2_buffer_data *buf);
#ifdef _DEBUG
/**
* Query the status of all buffers.
......
......@@ -88,6 +88,9 @@ struct v4l2_data {
int height;
int linesize;
struct v4l2_buffer_data buffers;
bool auto_reset;
int timeout_frames;
};
/* forward declarations */
......@@ -161,9 +164,21 @@ static void *v4l2_thread(void *vptr)
struct v4l2_buffer buf;
struct obs_source_frame out;
size_t plane_offsets[MAX_AV_PLANES];
int fps_num, fps_denom;
float ffps;
uint64_t timeout_usec;
blog(LOG_DEBUG, "%s: new capture thread", data->device_id);
/* Get framerate and calculate appropriate select timeout value. */
v4l2_unpack_tuple(&fps_num, &fps_denom, data->framerate);
ffps = (float)fps_denom / fps_num;
blog(LOG_DEBUG, "%s: framerate: %.2f fps", data->device_id, ffps);
/* Timeout set to 5 frame periods. */
timeout_usec = (1000000 * data->timeout_frames) / ffps;
blog(LOG_INFO, "%s: select timeout set to %ldus (%dx frame periods)",
data->device_id, timeout_usec, data->timeout_frames);
if (v4l2_start_capture(data->dev, &data->buffers) < 0)
goto exit;
......@@ -178,8 +193,10 @@ static void *v4l2_thread(void *vptr)
while (os_event_try(data->event) == EAGAIN) {
FD_ZERO(&fds);
FD_SET(data->dev, &fds);
tv.tv_sec = 1;
tv.tv_usec = 0;
/* Set timeout timevalue. */
tv.tv_sec = 0;
tv.tv_usec = timeout_usec;
r = select(data->dev + 1, &fds, NULL, NULL, &tv);
if (r < 0) {
......@@ -199,6 +216,18 @@ static void *v4l2_thread(void *vptr)
blog(LOG_ERROR, "%s: failed to log status",
data->device_id);
}
if (data->auto_reset) {
if (v4l2_reset_capture(data->dev,
&data->buffers) == 0)
blog(LOG_INFO,
"%s: stream reset successful",
data->device_id);
else
blog(LOG_ERROR, "%s: failed to reset",
data->device_id);
}
continue;
}
......@@ -264,6 +293,8 @@ static void v4l2_defaults(obs_data_t *settings)
obs_data_set_default_int(settings, "framerate", -1);
obs_data_set_default_int(settings, "color_range", VIDEO_RANGE_DEFAULT);
obs_data_set_default_bool(settings, "buffering", true);
obs_data_set_default_bool(settings, "auto_reset", false);
obs_data_set_default_int(settings, "timeout_frames", 5);
}
/**
......@@ -823,6 +854,13 @@ static obs_properties_t *v4l2_properties(void *vptr)
obs_properties_add_bool(props, "buffering",
obs_module_text("UseBuffering"));
obs_properties_add_bool(props, "auto_reset",
obs_module_text("AutoresetOnTimeout"));
obs_properties_add_int(props, "timeout_frames",
obs_module_text("FramesUntilTimeout"), 2, 120,
1);
// a group to contain the camera control
obs_properties_t *ctrl_props = obs_properties_create();
obs_properties_add_group(props, "controls",
......@@ -1067,6 +1105,8 @@ static void v4l2_update(void *vptr, obs_data_t *settings)
data->resolution = obs_data_get_int(settings, "resolution");
data->framerate = obs_data_get_int(settings, "framerate");
data->color_range = obs_data_get_int(settings, "color_range");
data->auto_reset = obs_data_get_bool(settings, "auto_reset");
data->timeout_frames = obs_data_get_int(settings, "timeout_frames");
v4l2_update_source_flags(data, settings);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册