Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b192ca98 authored by Jean-François Moine's avatar Jean-François Moine Committed by Mauro Carvalho Chehab
Browse files

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: default avatarJean-François Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent c6dc725c
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -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);

+30 −35
Original line number Diff line number Diff line
@@ -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,
+2 −3
Original line number Diff line number Diff line
@@ -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);
+5 −7
Original line number Diff line number Diff line
@@ -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);
		}
	}
}
+2 −4
Original line number Diff line number Diff line
@@ -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);
Loading