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:
parent
c6dc725c8e
commit
b192ca9837
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue