Skip to content

Commit

Permalink
V4L/DVB: gspca - main: Simplify image building
Browse files Browse the repository at this point in the history
The image pointer and its length are now in the main structure instead
of in the frame buffer. They are updated on application vidioc_qbuf and
in the URB interrupt function when ending an image.

Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Jean-François Moine authored and Mauro Carvalho Chehab committed Aug 2, 2010
1 parent c6dc725 commit b192ca9
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 98 deletions.
15 changes: 8 additions & 7 deletions drivers/media/video/gspca/cpia1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1760,22 +1760,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
data[25] == sd->params.roi.colEnd &&
data[26] == sd->params.roi.rowStart &&
data[27] == sd->params.roi.rowEnd) {
struct gspca_frame *frame = gspca_get_i_frame(gspca_dev);
u8 *image;

atomic_set(&sd->cam_exposure, data[39] * 2);
atomic_set(&sd->fps, data[41]);

if (frame == NULL) {
image = gspca_dev->image;
if (image == NULL) {
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}

/* Check for proper EOF for last frame */
if ((frame->data_end - frame->data) > 4 &&
frame->data_end[-4] == 0xff &&
frame->data_end[-3] == 0xff &&
frame->data_end[-2] == 0xff &&
frame->data_end[-1] == 0xff)
if (gspca_dev->image_len > 4 &&
image[gspca_dev->image_len - 4] == 0xff &&
image[gspca_dev->image_len - 3] == 0xff &&
image[gspca_dev->image_len - 2] == 0xff &&
image[gspca_dev->image_len - 1] == 0xff)
gspca_frame_add(gspca_dev, LAST_PACKET,
NULL, 0);

Expand Down
65 changes: 30 additions & 35 deletions drivers/media/video/gspca/gspca.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,19 +294,6 @@ static inline int gspca_input_connect(struct gspca_dev *dev)
}
#endif

/* get the current input frame buffer */
struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev)
{
struct gspca_frame *frame;

frame = gspca_dev->cur_frame;
if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
!= V4L2_BUF_FLAG_QUEUED)
return NULL;
return frame;
}
EXPORT_SYMBOL(gspca_get_i_frame);

/*
* fill a video frame from an URB and resubmit
*/
Expand All @@ -328,6 +315,8 @@ static void fill_frame(struct gspca_dev *gspca_dev,
urb->status = 0;
goto resubmit;
}
if (gspca_dev->image == NULL)
gspca_dev->last_packet_type = DISCARD_PACKET;
pkt_scan = gspca_dev->sd_desc->pkt_scan;
for (i = 0; i < urb->number_of_packets; i++) {

Expand Down Expand Up @@ -440,19 +429,16 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);

/* check the availability of the frame buffer */
frame = gspca_dev->cur_frame;
if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
!= V4L2_BUF_FLAG_QUEUED) {
gspca_dev->last_packet_type = DISCARD_PACKET;
if (gspca_dev->image == NULL)
return;
}

/* when start of a new frame, if the current frame buffer
* is not queued, discard the whole frame */
if (packet_type == FIRST_PACKET) {
frame->data_end = frame->data;
i = gspca_dev->fr_i;
j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j];
frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get());
frame->v4l2_buf.sequence = ++gspca_dev->sequence;
gspca_dev->image_len = 0;
} else if (gspca_dev->last_packet_type == DISCARD_PACKET) {
if (packet_type == LAST_PACKET)
gspca_dev->last_packet_type = packet_type;
Expand All @@ -461,34 +447,43 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,

/* append the packet to the frame buffer */
if (len > 0) {
if (frame->data_end - frame->data + len
> frame->v4l2_buf.length) {
PDEBUG(D_ERR|D_PACK, "frame overflow %zd > %d",
frame->data_end - frame->data + len,
frame->v4l2_buf.length);
if (gspca_dev->image_len + len > gspca_dev->frsz) {
PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
gspca_dev->image_len + len,
gspca_dev->frsz);
packet_type = DISCARD_PACKET;
} else {
memcpy(frame->data_end, data, len);
frame->data_end += len;
memcpy(gspca_dev->image + gspca_dev->image_len,
data, len);
gspca_dev->image_len += len;
}
}
gspca_dev->last_packet_type = packet_type;

/* if last packet, wake up the application and advance in the queue */
if (packet_type == LAST_PACKET) {
frame->v4l2_buf.bytesused = frame->data_end - frame->data;
i = gspca_dev->fr_i;
j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j];
frame->v4l2_buf.bytesused = gspca_dev->image_len;
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
i = (i + 1) % gspca_dev->nframes;
gspca_dev->fr_i = i;
PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
frame->v4l2_buf.bytesused,
gspca_dev->fr_q,
i,
gspca_dev->fr_o);
j = gspca_dev->fr_queue[i];
gspca_dev->cur_frame = &gspca_dev->frame[j];
frame = &gspca_dev->frame[j];
if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
== V4L2_BUF_FLAG_QUEUED) {
gspca_dev->image = frame->data;
} else {
gspca_dev->image = NULL;
}
}
}
EXPORT_SYMBOL(gspca_frame_add);
Expand Down Expand Up @@ -535,12 +530,12 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
frame->v4l2_buf.length = frsz;
frame->v4l2_buf.memory = gspca_dev->memory;
frame->v4l2_buf.sequence = 0;
frame->data = frame->data_end =
gspca_dev->frbuf + i * frsz;
frame->data = gspca_dev->frbuf + i * frsz;
frame->v4l2_buf.m.offset = i * frsz;
}
gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
gspca_dev->cur_frame = &gspca_dev->frame[0];
gspca_dev->image = NULL;
gspca_dev->image_len = 0;
gspca_dev->last_packet_type = DISCARD_PACKET;
gspca_dev->sequence = 0;
return 0;
Expand Down Expand Up @@ -1948,7 +1943,7 @@ static int vidioc_qbuf(struct file *file, void *priv,
i = gspca_dev->fr_q;
gspca_dev->fr_queue[i] = index;
if (gspca_dev->fr_i == i)
gspca_dev->cur_frame = frame;
gspca_dev->image = frame->data;
gspca_dev->fr_q = (i + 1) % gspca_dev->nframes;
PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d",
gspca_dev->fr_q,
Expand Down
5 changes: 2 additions & 3 deletions drivers/media/video/gspca/gspca.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ enum gspca_packet_type {

struct gspca_frame {
__u8 *data; /* frame buffer */
__u8 *data_end; /* end of frame while filling */
int vma_use_count;
struct v4l2_buffer v4l2_buf;
};
Expand Down Expand Up @@ -176,8 +175,9 @@ struct gspca_dev {

__u8 *frbuf; /* buffer for nframes */
struct gspca_frame frame[GSPCA_MAX_FRAMES];
struct gspca_frame *cur_frame; /* frame beeing filled */
u8 *image; /* image beeing filled */
__u32 frsz; /* frame size */
u32 image_len; /* current length of image */
char nframes; /* number of frames */
char fr_i; /* frame being filled */
char fr_q; /* next frame to queue */
Expand Down Expand Up @@ -226,7 +226,6 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
enum gspca_packet_type packet_type,
const u8 *data,
int len);
struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev);
#ifdef CONFIG_PM
int gspca_suspend(struct usb_interface *intf, pm_message_t message);
int gspca_resume(struct usb_interface *intf);
Expand Down
12 changes: 5 additions & 7 deletions drivers/media/video/gspca/m5602/m5602_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,30 +305,28 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev,
sd->frame_count);

} else {
struct gspca_frame *frame;
int cur_frame_len;

frame = gspca_get_i_frame(gspca_dev);
if (frame == NULL) {
if (gspca_dev->image == NULL) {
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}

cur_frame_len = frame->data_end - frame->data;
cur_frame_len = gspca_dev->image_len;
/* Remove urb header */
data += 4;
len -= 4;

if (cur_frame_len + len <= frame->v4l2_buf.length) {
if (cur_frame_len + len <= gspca_dev->frsz) {
PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes",
sd->frame_count, len);

gspca_frame_add(gspca_dev, INTER_PACKET,
data, len);
} else if (frame->v4l2_buf.length - cur_frame_len > 0) {
} else {
/* Add the remaining data up to frame size */
gspca_frame_add(gspca_dev, INTER_PACKET, data,
frame->v4l2_buf.length - cur_frame_len);
gspca_dev->frsz - cur_frame_len);
}
}
}
Expand Down
6 changes: 2 additions & 4 deletions drivers/media/video/gspca/ov519.c
Original file line number Diff line number Diff line change
Expand Up @@ -4162,7 +4162,6 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
struct gspca_frame *frame;

gspca_frame_add(gspca_dev, INTER_PACKET, data, len);

Expand All @@ -4172,9 +4171,8 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
the sensor and bridge are still syncing, so drop it. */
if (sd->first_frame) {
sd->first_frame--;
frame = gspca_get_i_frame(gspca_dev);
if (!frame || (frame->data_end - frame->data) <
(sd->gspca_dev.width * sd->gspca_dev.height))
if (gspca_dev->image_len <
sd->gspca_dev.width * sd->gspca_dev.height)
gspca_dev->last_packet_type = DISCARD_PACKET;
}
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Expand Down
7 changes: 2 additions & 5 deletions drivers/media/video/gspca/ov534.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,13 +987,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
data + 12, len - 12);
/* If this packet is marked as EOF, end the frame */
} else if (data[1] & UVC_STREAM_EOF) {
struct gspca_frame *frame;

sd->last_pts = 0;
frame = gspca_get_i_frame(gspca_dev);
if (frame == NULL)
if (gspca_dev->image == NULL)
goto discard;
if (frame->data_end - frame->data + (len - 12) !=
if (gspca_dev->image_len + len - 12 !=
gspca_dev->width * gspca_dev->height * 2) {
PDEBUG(D_PACK, "wrong sized frame");
goto discard;
Expand Down
24 changes: 11 additions & 13 deletions drivers/media/video/gspca/pac7302.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,6 @@ static const unsigned char pac_jpeg_header2[] = {
};

static void pac_start_frame(struct gspca_dev *gspca_dev,
struct gspca_frame *frame,
__u16 lines, __u16 samples_per_line)
{
unsigned char tmpbuf[4];
Expand All @@ -829,15 +828,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
struct gspca_frame *frame;
u8 *image;
unsigned char *sof;

sof = pac_find_sof(&sd->sof_read, data, len);
if (sof) {
int n, lum_offset, footer_length;

frame = gspca_get_i_frame(gspca_dev);
if (frame == NULL) {
image = gspca_dev->image;
if (image == NULL) {
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
Expand All @@ -852,16 +851,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* Finish decoding current frame */
n = (sof - data) - (footer_length + sizeof pac_sof_marker);
if (n < 0) {
frame->data_end += n;
gspca_dev->image_len += n;
n = 0;
} else {
gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
}
gspca_frame_add(gspca_dev, INTER_PACKET,
data, n);
if (gspca_dev->last_packet_type != DISCARD_PACKET &&
frame->data_end[-2] == 0xff &&
frame->data_end[-1] == 0xd9)
gspca_frame_add(gspca_dev, LAST_PACKET,
NULL, 0);
if (gspca_dev->last_packet_type != DISCARD_PACKET
&& image[gspca_dev->image_len - 2] == 0xff
&& image[gspca_dev->image_len - 1] == 0xd9)
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);

n = sof - data;
len -= n;
Expand All @@ -877,7 +875,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,

/* Start the new frame with the jpeg header */
/* The PAC7302 has the image rotated 90 degrees */
pac_start_frame(gspca_dev, frame,
pac_start_frame(gspca_dev,
gspca_dev->width, gspca_dev->height);
}
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Expand Down
24 changes: 11 additions & 13 deletions drivers/media/video/gspca/pac7311.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,6 @@ static const unsigned char pac_jpeg_header2[] = {
};

static void pac_start_frame(struct gspca_dev *gspca_dev,
struct gspca_frame *frame,
__u16 lines, __u16 samples_per_line)
{
unsigned char tmpbuf[4];
Expand All @@ -624,15 +623,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
u8 *image;
unsigned char *sof;
struct gspca_frame *frame;

sof = pac_find_sof(&sd->sof_read, data, len);
if (sof) {
int n, lum_offset, footer_length;

frame = gspca_get_i_frame(gspca_dev);
if (frame == NULL) {
image = gspca_dev->image;
if (image == NULL) {
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
Expand All @@ -647,16 +646,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* Finish decoding current frame */
n = (sof - data) - (footer_length + sizeof pac_sof_marker);
if (n < 0) {
frame->data_end += n;
gspca_dev->image_len += n;
n = 0;
} else {
gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
}
gspca_frame_add(gspca_dev, INTER_PACKET,
data, n);
if (gspca_dev->last_packet_type != DISCARD_PACKET &&
frame->data_end[-2] == 0xff &&
frame->data_end[-1] == 0xd9)
gspca_frame_add(gspca_dev, LAST_PACKET,
NULL, 0);
if (gspca_dev->last_packet_type != DISCARD_PACKET
&& image[gspca_dev->image_len - 2] == 0xff
&& image[gspca_dev->image_len - 1] == 0xd9)
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);

n = sof - data;
len -= n;
Expand All @@ -671,7 +669,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
atomic_set(&sd->avg_lum, -1);

/* Start the new frame with the jpeg header */
pac_start_frame(gspca_dev, frame,
pac_start_frame(gspca_dev,
gspca_dev->height, gspca_dev->width);
}
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Expand Down
Loading

0 comments on commit b192ca9

Please sign in to comment.