V4L/DVB: gspca - main: Simplify image building

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>
This commit is contained in:
Jean-François Moine 2010-06-27 03:08:19 -03:00 committed by Mauro Carvalho Chehab
parent c6dc725c8e
commit b192ca9837
10 changed files with 79 additions and 98 deletions

View File

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

View File

@ -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
*/
@ -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++) {
@ -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;
@ -461,26 +447,29 @@ 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,
@ -488,7 +477,13 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
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);
@ -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;
@ -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,

View File

@ -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;
};
@ -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 */
@ -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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1251,16 +1251,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
/* In raw mode we sometimes get some garbage after the frame
ignore this */
struct gspca_frame *frame;
int used;
int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
frame = gspca_get_i_frame(gspca_dev);
if (frame == NULL) {
if (gspca_dev->image == NULL) {
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
used = frame->data_end - frame->data;
used = gspca_dev->image_len;
if (used + len > size)
len = size - used;
}

View File

@ -3726,17 +3726,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* The vc0321 sends some additional data after sending the complete
* frame, we ignore this. */
if (sd->bridge == BRIDGE_VC0321) {
struct gspca_frame *frame;
int l;
int size, l;
frame = gspca_get_i_frame(gspca_dev);
if (frame == NULL) {
if (gspca_dev->image == NULL) {
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
l = frame->data_end - frame->data;
if (len > frame->v4l2_buf.length - l)
len = frame->v4l2_buf.length - l;
l = gspca_dev->image_len;
size = gspca_dev->frsz;
if (len > size - l)
len = size - l;
}
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
}