Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 47 additions & 40 deletions device.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ static const struct v4l2_frmsize_discrete vcam_sizes[] = {
{HD_720_WIDTH, HD_720_HEIGHT},
};

static const struct v4l2_fract vcam_frame_interval_min = {1001, 60000};
static const struct v4l2_fract vcam_frame_interval_max = {1001, 1001};
static const struct v4l2_fract vcam_frame_interval_default = {1001, 30000};

static int vcam_querycap(struct file *file,
void *priv,
struct v4l2_capability *cap)
Expand Down Expand Up @@ -230,12 +234,9 @@ static int vcam_enum_frameintervals(struct file *file,

fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
frm_step = &fival->stepwise;
frm_step->min.numerator = 1001;
frm_step->min.denominator = 60000;
frm_step->max.numerator = 1001;
frm_step->max.denominator = 1001;
frm_step->step.numerator = 1001;
frm_step->step.denominator = 60000;
frm_step->min = vcam_frame_interval_min;
frm_step->max = vcam_frame_interval_max;
frm_step->step = vcam_frame_interval_min;

return 0;
}
Expand All @@ -255,13 +256,30 @@ static int vcam_g_parm(struct file *file,

memset(cp, 0x00, sizeof(struct v4l2_captureparm));
cp->capability = V4L2_CAP_TIMEPERFRAME;
cp->timeperframe = dev->output_fps;
cp->timeperframe = dev->frame_interval;
cp->extendedmode = 0;
cp->readbuffers = 1;

return 0;
}

static void clamp_frame_interval(struct v4l2_fract *interval)
{
u64 value = (u64) interval->numerator *
vcam_frame_interval_min.denominator;
u64 min = (u64) vcam_frame_interval_min.numerator *
interval->denominator;
u64 max_value = (u64) interval->numerator *
vcam_frame_interval_max.denominator;
u64 max = (u64) vcam_frame_interval_max.numerator *
interval->denominator;

if (value < min)
*interval = vcam_frame_interval_min;
else if (max_value > max)
*interval = vcam_frame_interval_max;
}

static int vcam_s_parm(struct file *file,
void *priv,
struct v4l2_streamparm *sp)
Expand All @@ -277,14 +295,16 @@ static int vcam_s_parm(struct file *file,

cp->capability = V4L2_CAP_TIMEPERFRAME;
if (!cp->timeperframe.numerator || !cp->timeperframe.denominator)
cp->timeperframe = dev->output_fps;
else
dev->output_fps = cp->timeperframe;
cp->timeperframe = dev->frame_interval;
else {
clamp_frame_interval(&cp->timeperframe);
dev->frame_interval = cp->timeperframe;
}
cp->extendedmode = 0;
cp->readbuffers = 1;

pr_debug("FPS set to %d/%d\n", cp->timeperframe.numerator,
cp->timeperframe.denominator);
pr_debug("Frame interval set to %d/%d\n",
cp->timeperframe.numerator, cp->timeperframe.denominator);
return 0;
}

Expand Down Expand Up @@ -661,10 +681,9 @@ int submitter_thread(void *data)

while (!kthread_should_stop()) {
struct vcam_out_buffer *buf;
int timeout_ms, timeout;

/* Do something and sleep */
int computation_time_jiff = jiffies;
unsigned long frame_interval;
unsigned long processing_start = jiffies;
unsigned long processing_time;
spin_lock_irqsave(&dev->out_q_slock, flags);
if (list_empty(&q->active)) {
pr_debug("Buffer queue is empty\n");
Expand All @@ -691,28 +710,17 @@ int submitter_thread(void *data)
}

have_a_nap:
if (!dev->output_fps.denominator) {
dev->output_fps.numerator = 1001;
dev->output_fps.denominator = 30000;
}
timeout_ms = dev->output_fps.denominator / dev->output_fps.numerator;
if (!timeout_ms) {
dev->output_fps.numerator = 1001;
dev->output_fps.denominator = 60000;
timeout_ms =
dev->output_fps.denominator / dev->output_fps.numerator;
}

/* Compute timeout and update FPS */
computation_time_jiff = jiffies - computation_time_jiff;
timeout = msecs_to_jiffies(timeout_ms);
if (computation_time_jiff > timeout) {
int computation_time_ms = msecs_to_jiffies(computation_time_jiff);
dev->output_fps.numerator = 1001;
dev->output_fps.denominator = 1000 * computation_time_ms;
} else if (timeout > computation_time_jiff) {
schedule_timeout_interruptible(timeout - computation_time_jiff);
}
if (!dev->frame_interval.denominator)
dev->frame_interval = vcam_frame_interval_default;

frame_interval = max_t(
unsigned long, 1,
DIV_ROUND_CLOSEST_ULL(
(u64) dev->frame_interval.numerator * HZ,
dev->frame_interval.denominator));
processing_time = jiffies - processing_start;
if (frame_interval > processing_time)
schedule_timeout_interruptible(frame_interval - processing_time);
}

return 0;
Expand Down Expand Up @@ -856,8 +864,7 @@ struct vcam_device *create_vcam_device(size_t idx,
}
vcam->fb_isopen = 0;

vcam->output_fps.numerator = 1001;
vcam->output_fps.denominator = 30000;
vcam->frame_interval = vcam_frame_interval_default;

return vcam;

Expand Down
4 changes: 2 additions & 2 deletions device.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ struct vcam_device {
struct vb2_queue vb_out_vidq;
struct vcam_out_queue vcam_out_vidq;
spinlock_t out_q_slock;
/* Output framerate */
struct v4l2_fract output_fps;
/* Output frame interval */
struct v4l2_fract frame_interval;

/* Input framebuffer */
char vcam_fb_fname[FB_NAME_MAXLENGTH];
Expand Down