* [RFC PATCH v9 1/6] media: videobuf2: Move timestamp to vb2_buffer
2015-11-03 10:16 [RFC PATCH v9] Refactoring Videobuf2 for common use Junghak Sung
@ 2015-11-03 10:16 ` Junghak Sung
2015-11-04 12:28 ` Hans Verkuil
2015-11-03 10:16 ` [RFC PATCH v9 2/6] media: videobuf2: Add set_timestamp to struct vb2_queue Junghak Sung
` (4 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Junghak Sung @ 2015-11-03 10:16 UTC (permalink / raw)
To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus,
pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
Junghak Sung
Move timestamp from struct vb2_v4l2_buffer to struct vb2_buffer
for common use, and change its type to u64 in order to handling
y2038 problem. This patch also includes all device drivers' changes related to
this restructuring.
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
drivers/input/touchscreen/sur40.c | 2 +-
drivers/media/dvb-frontends/rtl2832_sdr.c | 2 +-
drivers/media/pci/cobalt/cobalt-irq.c | 2 +-
drivers/media/pci/cx23885/cx23885-core.c | 2 +-
drivers/media/pci/cx23885/cx23885-video.c | 2 +-
drivers/media/pci/cx25821/cx25821-video.c | 2 +-
drivers/media/pci/cx88/cx88-core.c | 2 +-
drivers/media/pci/dt3155/dt3155.c | 2 +-
drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 2 +-
drivers/media/pci/saa7134/saa7134-core.c | 2 +-
drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c | 4 ++--
drivers/media/pci/solo6x10/solo6x10-v4l2.c | 2 +-
drivers/media/pci/sta2x11/sta2x11_vip.c | 2 +-
drivers/media/pci/tw68/tw68-video.c | 2 +-
drivers/media/platform/am437x/am437x-vpfe.c | 2 +-
drivers/media/platform/blackfin/bfin_capture.c | 2 +-
drivers/media/platform/coda/coda-bit.c | 6 +++---
drivers/media/platform/coda/coda.h | 2 +-
drivers/media/platform/davinci/vpbe_display.c | 2 +-
drivers/media/platform/davinci/vpif_capture.c | 2 +-
drivers/media/platform/davinci/vpif_display.c | 6 +++---
drivers/media/platform/exynos-gsc/gsc-m2m.c | 4 ++--
drivers/media/platform/exynos4-is/fimc-capture.c | 2 +-
drivers/media/platform/exynos4-is/fimc-isp-video.c | 2 +-
drivers/media/platform/exynos4-is/fimc-lite.c | 2 +-
drivers/media/platform/exynos4-is/fimc-m2m.c | 2 +-
drivers/media/platform/m2m-deinterlace.c | 2 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +-
drivers/media/platform/mx2_emmaprp.c | 2 +-
drivers/media/platform/omap3isp/ispvideo.c | 2 +-
drivers/media/platform/rcar_jpu.c | 2 +-
drivers/media/platform/s3c-camif/camif-capture.c | 2 +-
drivers/media/platform/s5p-g2d/g2d.c | 2 +-
drivers/media/platform/s5p-jpeg/jpeg-core.c | 4 ++--
drivers/media/platform/s5p-mfc/s5p_mfc.c | 4 ++--
drivers/media/platform/sh_veu.c | 2 +-
drivers/media/platform/sh_vou.c | 2 +-
drivers/media/platform/soc_camera/atmel-isi.c | 2 +-
drivers/media/platform/soc_camera/mx2_camera.c | 2 +-
drivers/media/platform/soc_camera/mx3_camera.c | 2 +-
drivers/media/platform/soc_camera/rcar_vin.c | 2 +-
.../platform/soc_camera/sh_mobile_ceu_camera.c | 2 +-
drivers/media/platform/sti/bdisp/bdisp-v4l2.c | 4 ++--
drivers/media/platform/ti-vpe/vpe.c | 2 +-
drivers/media/platform/vim2m.c | 2 +-
drivers/media/platform/vivid/vivid-kthread-cap.c | 7 ++++---
drivers/media/platform/vivid/vivid-kthread-out.c | 10 ++++++----
drivers/media/platform/vivid/vivid-sdr-cap.c | 5 +++--
drivers/media/platform/vivid/vivid-vbi-cap.c | 10 ++++++----
drivers/media/platform/vsp1/vsp1_video.c | 2 +-
drivers/media/platform/xilinx/xilinx-dma.c | 2 +-
drivers/media/usb/airspy/airspy.c | 2 +-
drivers/media/usb/au0828/au0828-video.c | 2 +-
drivers/media/usb/em28xx/em28xx-video.c | 2 +-
drivers/media/usb/go7007/go7007-driver.c | 2 +-
drivers/media/usb/hackrf/hackrf.c | 4 ++--
drivers/media/usb/pwc/pwc-if.c | 3 +--
drivers/media/usb/s2255/s2255drv.c | 2 +-
drivers/media/usb/stk1160/stk1160-video.c | 2 +-
drivers/media/usb/usbtv/usbtv-video.c | 2 +-
drivers/media/usb/uvc/uvc_video.c | 15 +++++----------
drivers/media/v4l2-core/videobuf2-v4l2.c | 10 +++++-----
drivers/staging/media/davinci_vpfe/vpfe_video.c | 2 +-
drivers/staging/media/omap4iss/iss_video.c | 2 +-
drivers/usb/gadget/function/uvc_queue.c | 2 +-
include/media/videobuf2-core.h | 2 ++
include/media/videobuf2-v4l2.h | 2 --
include/trace/events/v4l2.h | 4 ++--
include/trace/events/vb2.h | 7 +++++--
69 files changed, 107 insertions(+), 104 deletions(-)
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index d214f22..1a2eeaf 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -444,7 +444,7 @@ static void sur40_process_video(struct sur40_state *sur40)
goto err_poll;
/* mark as finished */
- v4l2_get_timestamp(&new_buf->vb.timestamp);
+ new_buf->vb.vb2_buf.timestamp = ktime_get_ns();
new_buf->vb.sequence = sur40->sequence++;
new_buf->vb.field = V4L2_FIELD_NONE;
vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index dcd8d94..606c3b8 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -310,7 +310,7 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
len = rtl2832_sdr_convert_stream(dev, ptr, urb->transfer_buffer,
urb->actual_length);
vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
- v4l2_get_timestamp(&fbuf->vb.timestamp);
+ fbuf->vb.vb2_buf.timestamp = ktime_get_ns();
fbuf->vb.sequence = dev->sequence++;
vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c
index 3de26d0..08761b8 100644
--- a/drivers/media/pci/cobalt/cobalt-irq.c
+++ b/drivers/media/pci/cobalt/cobalt-irq.c
@@ -134,7 +134,7 @@ done:
skip = true;
s->skip_first_frames--;
}
- v4l2_get_timestamp(&cb->vb.timestamp);
+ cb->vb.vb2_buf.timestamp = ktime_get_ns();
/* TODO: the sequence number should be read from the FPGA so we
also know about dropped frames. */
cb->vb.sequence = s->sequence++;
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index bc1c960..4d884d7 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -427,7 +427,7 @@ static void cx23885_wakeup(struct cx23885_tsport *port,
buf = list_entry(q->active.next,
struct cx23885_buffer, queue);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
buf->vb.sequence = q->count++;
dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
buf->vb.vb2_buf.index,
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 71a80e2..53ecf7d 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -105,7 +105,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
struct cx23885_buffer, queue);
buf->vb.sequence = q->count++;
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
buf->vb.vb2_buf.index, count, q->count);
list_del(&buf->queue);
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index 26e3e29..6a43fa5 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -130,7 +130,7 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
buf = list_entry(dmaq->active.next,
struct cx25821_buffer, queue);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
buf->vb.sequence = dmaq->count++;
list_del(&buf->queue);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index 9a43c78..46fe8c1 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -518,7 +518,7 @@ void cx88_wakeup(struct cx88_core *core,
buf = list_entry(q->active.next,
struct cx88_buffer, list);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
buf->vb.field = core->field;
buf->vb.sequence = q->count++;
list_del(&buf->list);
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
index d84abde..7936204 100644
--- a/drivers/media/pci/dt3155/dt3155.c
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -271,7 +271,7 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
spin_lock(&ipd->lock);
if (ipd->curr_buf && !list_empty(&ipd->dmaq)) {
- v4l2_get_timestamp(&ipd->curr_buf->timestamp);
+ ipd->curr_buf->vb2_buf.timestamp = ktime_get_ns();
ipd->curr_buf->sequence = ipd->sequence++;
ipd->curr_buf->field = V4L2_FIELD_NONE;
vb2_buffer_done(&ipd->curr_buf->vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
index 83c90d3..8e28536 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -580,7 +580,7 @@ static void netup_unidvb_dma_worker(struct work_struct *work)
dev_dbg(&ndev->pci_dev->dev,
"%s(): buffer %p done, size %d\n",
__func__, buf, buf->size);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 87f39f9..4665645 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -309,7 +309,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev,
core_dbg("buffer_finish %p\n", q->curr);
/* finish current buffer */
- v4l2_get_timestamp(&q->curr->vb2.timestamp);
+ q->curr->vb2.vb2_buf.timestamp = ktime_get_ns();
q->curr->vb2.sequence = q->seq_nr++;
vb2_buffer_done(&q->curr->vb2.vb2_buf, state);
q->curr = NULL;
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 1bd2fd4..61df3e4 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -531,8 +531,8 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
if (!ret) {
vbuf->sequence = solo_enc->sequence++;
- vbuf->timestamp.tv_sec = vop_sec(vh);
- vbuf->timestamp.tv_usec = vop_usec(vh);
+ vb->timestamp = ((u64) vop_sec(vh) * NSEC_PER_SEC) +
+ (vop_usec(vh) * NSEC_PER_USEC);
/* Check for motion flags */
if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 26df903..44b00b8 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -225,7 +225,7 @@ finish_buf:
vb2_set_plane_payload(vb, 0,
solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
vbuf->sequence = solo_dev->sequence++;
- v4l2_get_timestamp(&vbuf->timestamp);
+ vb->timestamp = ktime_get_ns();
}
vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 6367b45..434cda2 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -817,7 +817,7 @@ static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip)
/* Disable acquisition */
reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) & ~DVP_CTL_ENA);
/* Remove the active buffer from the list */
- v4l2_get_timestamp(&vip->active->vb.timestamp);
+ vip->active->vb.vb2_buf.timestamp = ktime_get_ns();
vip->active->vb.sequence = vip->sequence++;
vb2_buffer_done(&vip->active->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index 4c3293d..a736811 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -1016,7 +1016,7 @@ void tw68_irq_video_done(struct tw68_dev *dev, unsigned long status)
buf = list_entry(dev->active.next, struct tw68_buf, list);
list_del(&buf->list);
spin_unlock(&dev->slock);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
buf->vb.field = dev->field;
buf->vb.sequence = dev->seqnr++;
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index f0480d6..c56c3ec 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -1281,7 +1281,7 @@ static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe)
*/
static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe)
{
- v4l2_get_timestamp(&vpfe->cur_frm->vb.timestamp);
+ vpfe->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
vpfe->cur_frm->vb.field = vpfe->fmt.fmt.pix.field;
vpfe->cur_frm->vb.sequence = vpfe->sequence++;
vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 7764b9c..ebc9962 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -406,7 +406,7 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
spin_lock(&bcap_dev->lock);
if (!list_empty(&bcap_dev->dma_queue)) {
- v4l2_get_timestamp(&vbuf->timestamp);
+ vb->timestamp = ktime_get_ns();
if (ppi->err) {
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
ppi->err = false;
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 654e964..21beb97 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -279,7 +279,7 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming)
if (meta) {
meta->sequence = src_buf->sequence;
meta->timecode = src_buf->timecode;
- meta->timestamp = src_buf->timestamp;
+ meta->timestamp = src_buf->vb2_buf.timestamp;
meta->start = start;
meta->end = ctx->bitstream_fifo.kfifo.in &
ctx->bitstream_fifo.kfifo.mask;
@@ -1364,7 +1364,7 @@ static void coda_finish_encode(struct coda_ctx *ctx)
dst_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME;
}
- dst_buf->timestamp = src_buf->timestamp;
+ dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_buf->flags |=
src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
@@ -2040,7 +2040,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
dst_buf->flags |= ctx->frame_types[ctx->display_idx];
meta = &ctx->frame_metas[ctx->display_idx];
dst_buf->timecode = meta->timecode;
- dst_buf->timestamp = meta->timestamp;
+ dst_buf->vb2_buf.timestamp = meta->timestamp;
trace_coda_dec_rot_done(ctx, dst_buf, meta);
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 96532b0..6cda81e 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -138,7 +138,7 @@ struct coda_buffer_meta {
struct list_head list;
u32 sequence;
struct v4l2_timecode timecode;
- struct timeval timestamp;
+ u64 timestamp;
u32 start;
u32 end;
};
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index 6d91422..6c3030d 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -74,7 +74,7 @@ static void vpbe_isr_even_field(struct vpbe_display *disp_obj,
if (layer->cur_frm == layer->next_frm)
return;
- v4l2_get_timestamp(&layer->cur_frm->vb.timestamp);
+ layer->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
/* Make cur_frm pointing to next_frm */
layer->cur_frm = layer->next_frm;
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index c1e573b..7a5c1aa 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -331,7 +331,7 @@ static struct vb2_ops video_qops = {
*/
static void vpif_process_buffer_complete(struct common_obj *common)
{
- v4l2_get_timestamp(&common->cur_frm->vb.timestamp);
+ common->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
/* Make curFrm pointing to nextFrm */
common->cur_frm = common->next_frm;
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index fd27803..f33de36 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -330,7 +330,7 @@ static void process_interlaced_mode(int fid, struct common_obj *common)
/* one frame is displayed If next frame is
* available, release cur_frm and move on */
/* Copy frame display time */
- v4l2_get_timestamp(&common->cur_frm->vb.timestamp);
+ common->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
/* Change status of the cur_frm */
vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
VB2_BUF_STATE_DONE);
@@ -386,8 +386,8 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
if (!channel_first_int[i][channel_id]) {
/* Mark status of the cur_frm to
* done and unlock semaphore on it */
- v4l2_get_timestamp(
- &common->cur_frm->vb.timestamp);
+ common->cur_frm->vb.vb2_buf.timestamp =
+ ktime_get_ns();
vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
VB2_BUF_STATE_DONE);
/* Make cur_frm pointing to next_frm */
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index d82e717..70bf10f 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -86,7 +86,7 @@ void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state)
dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
if (src_vb && dst_vb) {
- dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
dst_vb->timecode = src_vb->timecode;
dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_vb->flags |=
@@ -125,7 +125,7 @@ static int gsc_get_bufs(struct gsc_ctx *ctx)
if (ret)
return ret;
- dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
return 0;
}
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index 99e5732..5d4b394 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -193,7 +193,7 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) {
v_buf = fimc_active_queue_pop(cap);
- v4l2_get_timestamp(&v_buf->vb.timestamp);
+ v_buf->vb.vb2_buf.timestamp = ktime_get_ns();
v_buf->vb.sequence = cap->frame_count++;
vb2_buffer_done(&v_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
index 6e66484..f3078b4 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -254,7 +254,7 @@ void fimc_isp_video_irq_handler(struct fimc_is *is)
buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count;
vbuf = &video->buffers[buf_index]->vb;
- v4l2_get_timestamp(&vbuf->timestamp);
+ vbuf->vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
video->buf_mask &= ~BIT(buf_index);
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 60660c3..990d74c 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -292,7 +292,7 @@ static irqreturn_t flite_irq_handler(int irq, void *priv)
test_bit(ST_FLITE_RUN, &fimc->state) &&
!list_empty(&fimc->active_buf_q)) {
vbuf = fimc_lite_active_queue_pop(fimc);
- v4l2_get_timestamp(&vbuf->vb.timestamp);
+ vbuf->vb.vb2_buf.timestamp = ktime_get_ns();
vbuf->vb.sequence = fimc->frame_count++;
flite_hw_mask_dma_buffer(fimc, vbuf->index);
vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
index 4d1d64a4..0d72b50 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -132,7 +132,7 @@ static void fimc_device_run(void *priv)
if (ret)
goto dma_unlock;
- dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_vb->flags |=
src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index 29973f9..e27fb82 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -207,7 +207,7 @@ static void dma_callback(void *data)
src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
- dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_vb->flags |=
src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index aa2b440..65bcd9c 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -226,7 +226,7 @@ static void mcam_buffer_done(struct mcam_camera *cam, int frame,
vbuf->vb2_buf.planes[0].bytesused = cam->pix_format.sizeimage;
vbuf->sequence = cam->buf_seq[frame];
vbuf->field = V4L2_FIELD_NONE;
- v4l2_get_timestamp(&vbuf->timestamp);
+ vbuf->vb2_buf.timestamp = ktime_get_ns();
vb2_set_plane_payload(&vbuf->vb2_buf, 0, cam->pix_format.sizeimage);
vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 03a1b60..e0e36ea 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -375,7 +375,7 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data)
src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
- dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
dst_vb->flags &=
~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_vb->flags |=
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index f4f5916..04ffb9f 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -467,7 +467,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
list_del(&buf->irqlist);
spin_unlock_irqrestore(&video->irqlock, flags);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
/* Do frame number propagation only if this is the output video node.
* Frame number either comes from the CSI receivers or it gets
diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
index f8e3e83..6e0871b 100644
--- a/drivers/media/platform/rcar_jpu.c
+++ b/drivers/media/platform/rcar_jpu.c
@@ -1560,7 +1560,7 @@ static irqreturn_t jpu_irq_handler(int irq, void *dev_id)
}
dst_buf->field = src_buf->field;
- dst_buf->timestamp = src_buf->timestamp;
+ dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
if (src_buf->flags & V4L2_BUF_FLAG_TIMECODE)
dst_buf->timecode = src_buf->timecode;
dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index 537b858..cbaf464 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -338,7 +338,7 @@ irqreturn_t s3c_camif_irq_handler(int irq, void *priv)
if (!WARN_ON(vbuf == NULL)) {
/* Dequeue a filled buffer */
- v4l2_get_timestamp(&vbuf->vb.timestamp);
+ vbuf->vb.vb2_buf.timestamp = ktime_get_ns();
vbuf->vb.sequence = vp->frame_sequence++;
vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index e1936d9..658e091 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -552,7 +552,7 @@ static irqreturn_t g2d_isr(int irq, void *prv)
BUG_ON(dst == NULL);
dst->timecode = src->timecode;
- dst->timestamp = src->timestamp;
+ dst->vb2_buf.timestamp = src->vb2_buf.timestamp;
dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst->flags |=
src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 4a608cb..e9b0e32 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -2621,7 +2621,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
}
dst_buf->timecode = src_buf->timecode;
- dst_buf->timestamp = src_buf->timestamp;
+ dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_buf->flags |=
src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
@@ -2752,7 +2752,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
dst_buf->timecode = src_buf->timecode;
- dst_buf->timestamp = src_buf->timestamp;
+ dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
v4l2_m2m_buf_done(src_buf, state);
if (curr_ctx->mode == S5P_JPEG_ENCODE)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 3ffe2ec..0effb2f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -233,8 +233,8 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
== dec_y_addr) {
dst_buf->b->timecode =
src_buf->b->timecode;
- dst_buf->b->timestamp =
- src_buf->b->timestamp;
+ dst_buf->b->vb2_buf.timestamp =
+ src_buf->b->vb2_buf.timestamp;
dst_buf->b->flags &=
~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_buf->b->flags |=
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index d6ab33e..720e40c 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -1107,7 +1107,7 @@ static irqreturn_t sh_veu_isr(int irq, void *dev_id)
if (!src || !dst)
return IRQ_NONE;
- dst->timestamp = src->timestamp;
+ dst->vb2_buf.timestamp = src->vb2_buf.timestamp;
dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst->flags |=
src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 2231f89..ad53337 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -1071,7 +1071,7 @@ static irqreturn_t sh_vou_isr(int irq, void *dev_id)
list_del(&vb->list);
- v4l2_get_timestamp(&vb->vb.timestamp);
+ vb->vb.vb2_buf.timestamp = ktime_get_ns();
vb->vb.sequence = vou_dev->sequence++;
vb->vb.field = V4L2_FIELD_INTERLACED;
vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 454f68f..b73c07b 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -165,7 +165,7 @@ static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi)
struct frame_buffer *buf = isi->active;
list_del_init(&buf->list);
- v4l2_get_timestamp(&vbuf->timestamp);
+ vbuf->vb2_buf.timestamp = ktime_get_ns();
vbuf->sequence = isi->sequence++;
vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index 1f28d21..ace8eb0 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -1351,7 +1351,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
vb2_get_plane_payload(vb, 0));
list_del_init(&buf->internal.queue);
- v4l2_get_timestamp(&vbuf->timestamp);
+ vb->timestamp = ktime_get_ns();
vbuf->sequence = pcdev->frame_count;
if (err)
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index 49c3a25..a9c9916 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -155,7 +155,7 @@ static void mx3_cam_dma_done(void *arg)
struct mx3_camera_buffer *buf = to_mx3_vb(vb);
list_del_init(&buf->queue);
- v4l2_get_timestamp(&vb->timestamp);
+ vb->vb2_buf.timestamp = ktime_get_ns();
vb->field = mx3_cam->field;
vb->sequence = mx3_cam->sequence++;
vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index efe57b2..e30559b 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -912,7 +912,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data)
priv->queue_buf[slot]->field = priv->field;
priv->queue_buf[slot]->sequence = priv->sequence++;
- v4l2_get_timestamp(&priv->queue_buf[slot]->timestamp);
+ priv->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf,
VB2_BUF_STATE_DONE);
priv->queue_buf[slot] = NULL;
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 67a669d..fa0faa9 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -533,7 +533,7 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
pcdev->active = NULL;
ret = sh_mobile_ceu_capture(pcdev);
- v4l2_get_timestamp(&vbuf->timestamp);
+ vbuf->vb2_buf.timestamp = ktime_get_ns();
if (!ret) {
vbuf->field = pcdev->field;
vbuf->sequence = pcdev->sequence++;
diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
index a0d267e..ad122cc 100644
--- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
@@ -191,7 +191,7 @@ static void bdisp_job_finish(struct bdisp_ctx *ctx, int vb_state)
dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
if (src_vb && dst_vb) {
- dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
dst_vb->timecode = src_vb->timecode;
dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_vb->flags |= src_vb->flags &
@@ -297,7 +297,7 @@ static int bdisp_get_bufs(struct bdisp_ctx *ctx)
if (ret)
return ret;
- dst_vb->timestamp = src_vb->timestamp;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
return 0;
}
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index de24eff..83acb83 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -1288,7 +1288,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
d_vb = ctx->dst_vb;
d_vb->flags = s_vb->flags;
- d_vb->timestamp = s_vb->timestamp;
+ d_vb->vb2_buf.timestamp = s_vb->vb2_buf.timestamp;
if (s_vb->flags & V4L2_BUF_FLAG_TIMECODE)
d_vb->timecode = s_vb->timecode;
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index e18fb9f..06a0e04 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -235,7 +235,7 @@ static int device_process(struct vim2m_ctx *ctx,
out_vb->sequence =
get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
in_vb->sequence = q_data->sequence++;
- out_vb->timestamp = in_vb->timestamp;
+ out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp;
if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE)
out_vb->timecode = in_vb->timecode;
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 83cc6d3..b0ad054 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -441,7 +441,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
* "Start of Exposure".
*/
if (dev->tstamp_src_is_soe)
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
/*
* 60 Hz standards start with the bottom field, 50 Hz standards
@@ -558,8 +558,9 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
* the timestamp now.
*/
if (!dev->tstamp_src_is_soe)
- v4l2_get_timestamp(&buf->vb.timestamp);
- buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
+ buf->vb.vb2_buf.timestamp +=
+ ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
}
/*
diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
index c2c46dc..6fd02c9 100644
--- a/drivers/media/platform/vivid/vivid-kthread-out.c
+++ b/drivers/media/platform/vivid/vivid-kthread-out.c
@@ -95,8 +95,9 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
*/
vid_out_buf->vb.sequence /= 2;
}
- v4l2_get_timestamp(&vid_out_buf->vb.timestamp);
- vid_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ vid_out_buf->vb.vb2_buf.timestamp = ktime_get_ns();
+ vid_out_buf->vb.vb2_buf.timestamp +=
+ ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vid_out buffer %d done\n",
@@ -108,8 +109,9 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
vivid_sliced_vbi_out_process(dev, vbi_out_buf);
vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
- v4l2_get_timestamp(&vbi_out_buf->vb.timestamp);
- vbi_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ vbi_out_buf->vb.vb2_buf.timestamp = ktime_get_ns();
+ vbi_out_buf->vb.vb2_buf.timestamp +=
+ ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vbi_out buffer %d done\n",
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index 082c401..dbdb43d 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -117,8 +117,9 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
if (sdr_cap_buf) {
sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count;
vivid_sdr_cap_process(dev, sdr_cap_buf);
- v4l2_get_timestamp(&sdr_cap_buf->vb.timestamp);
- sdr_cap_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ sdr_cap_buf->vb.vb2_buf.timestamp = ktime_get_ns();
+ sdr_cap_buf->vb.vb2_buf.timestamp +=
+ ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
vb2_buffer_done(&sdr_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dev->dqbuf_error = false;
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index e903d02..2f5f330 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -108,8 +108,9 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode))
vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
- v4l2_get_timestamp(&buf->vb.timestamp);
- buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
+ buf->vb.vb2_buf.timestamp +=
+ ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
}
@@ -133,8 +134,9 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
vbuf[i] = dev->vbi_gen.data[i];
}
- v4l2_get_timestamp(&buf->vb.timestamp);
- buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
+ buf->vb.vb2_buf.timestamp +=
+ ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
}
static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg,
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 5ce88e1..2b2c94d 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -611,7 +611,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
spin_unlock_irqrestore(&video->irqlock, flags);
done->buf.sequence = video->sequence++;
- v4l2_get_timestamp(&done->buf.timestamp);
+ done->buf.vb2_buf.timestamp = ktime_get_ns();
for (i = 0; i < done->buf.vb2_buf.num_planes; ++i)
vb2_set_plane_payload(&done->buf.vb2_buf, i, done->length[i]);
vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index d11cc70..24b897a3 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -303,7 +303,7 @@ static void xvip_dma_complete(void *param)
buf->buf.field = V4L2_FIELD_NONE;
buf->buf.sequence = dma->sequence++;
- v4l2_get_timestamp(&buf->buf.timestamp);
+ buf->buf.vb2_buf.timestamp = ktime_get_ns();
vb2_set_plane_payload(&buf->buf.vb2_buf, 0, dma->format.sizeimage);
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index fcbb497..a77fb56 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -316,7 +316,7 @@ static void airspy_urb_complete(struct urb *urb)
len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
urb->actual_length);
vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
- v4l2_get_timestamp(&fbuf->vb.timestamp);
+ fbuf->vb.vb2_buf.timestamp = ktime_get_ns();
fbuf->vb.sequence = s->sequence++;
vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 45c622e..4a80db6 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -314,7 +314,7 @@ static inline void buffer_filled(struct au0828_dev *dev,
vb->sequence = dev->vbi_frame_count++;
vb->field = V4L2_FIELD_INTERLACED;
- v4l2_get_timestamp(&vb->timestamp);
+ vb->vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 6a3cf34..37f738c 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -438,7 +438,7 @@ static inline void finish_buffer(struct em28xx *dev,
buf->vb.field = V4L2_FIELD_NONE;
else
buf->vb.field = V4L2_FIELD_INTERLACED;
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
index ae1cfa7..05b1126 100644
--- a/drivers/media/usb/go7007/go7007-driver.c
+++ b/drivers/media/usb/go7007/go7007-driver.c
@@ -466,7 +466,7 @@ static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buf
else
go7007_set_motion_regions(go, vb, 0);
- v4l2_get_timestamp(&vb->vb.timestamp);
+ vb->vb.vb2_buf.timestamp = ktime_get_ns();
vb_tmp = vb;
spin_lock(&go->spinlock);
list_del(&vb->list);
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index e05bfec..b3336d2 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -517,7 +517,7 @@ static void hackrf_urb_complete_in(struct urb *urb)
urb->transfer_buffer, len);
vb2_set_plane_payload(&buffer->vb.vb2_buf, 0, len);
buffer->vb.sequence = dev->sequence++;
- v4l2_get_timestamp(&buffer->vb.timestamp);
+ buffer->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE);
exit_usb_submit_urb:
usb_submit_urb(urb, GFP_ATOMIC);
@@ -562,7 +562,7 @@ static void hackrf_urb_complete_out(struct urb *urb)
vb2_plane_vaddr(&buffer->vb.vb2_buf, 0), len);
urb->actual_length = len;
buffer->vb.sequence = dev->sequence++;
- v4l2_get_timestamp(&buffer->vb.timestamp);
+ buffer->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE);
exit_usb_submit_urb:
usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index b79c36f..d55fda5 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -316,8 +316,7 @@ static void pwc_isoc_handler(struct urb *urb)
struct pwc_frame_buf *fbuf = pdev->fill_buf;
if (pdev->vsync == 1) {
- v4l2_get_timestamp(
- &fbuf->vb.timestamp);
+ fbuf->vb.vb2_buf.timestamp = ktime_get_ns();
pdev->vsync = 2;
}
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index e7acb12..96ddbae 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -574,7 +574,7 @@ static void s2255_got_frame(struct s2255_vc *vc, int jpgsize)
buf = list_entry(vc->buf_list.next,
struct s2255_buffer, list);
list_del(&buf->list);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
buf->vb.field = vc->field;
buf->vb.sequence = vc->frame_count;
spin_unlock_irqrestore(&vc->qlock, flags);
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
index 75654e6..46191d5 100644
--- a/drivers/media/usb/stk1160/stk1160-video.c
+++ b/drivers/media/usb/stk1160/stk1160-video.c
@@ -99,7 +99,7 @@ void stk1160_buffer_done(struct stk1160 *dev)
buf->vb.sequence = dev->sequence++;
buf->vb.field = V4L2_FIELD_INTERLACED;
buf->vb.vb2_buf.planes[0].bytesused = buf->bytesused;
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index e645c9d..89fd7bb 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -322,7 +322,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
buf->vb.field = V4L2_FIELD_INTERLACED;
buf->vb.sequence = usbtv->sequence++;
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
vb2_buffer_done(&buf->vb.vb2_buf, state);
list_del(&buf->list);
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 2b276ab..f126859 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -694,19 +694,16 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
ts.tv_nsec -= NSEC_PER_SEC;
}
- uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu "
- "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
+ uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu "
+ "buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
stream->dev->name,
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
- y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
- vbuf->timestamp.tv_sec,
- (unsigned long)vbuf->timestamp.tv_usec,
+ y, timespec_to_ns(&ts), vbuf->vb2_buf.timestamp,
x1, first->host_sof, first->dev_sof,
x2, last->host_sof, last->dev_sof, y1, y2);
/* Update the V4L2 buffer. */
- vbuf->timestamp.tv_sec = ts.tv_sec;
- vbuf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ vbuf->vb2_buf.timestamp = timespec_to_ns(&ts);
done:
spin_unlock_irqrestore(&stream->clock.lock, flags);
@@ -1034,9 +1031,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
buf->buf.field = V4L2_FIELD_NONE;
buf->buf.sequence = stream->sequence;
- buf->buf.timestamp.tv_sec = ts.tv_sec;
- buf->buf.timestamp.tv_usec =
- ts.tv_nsec / NSEC_PER_USEC;
+ buf->buf.vb2_buf.timestamp = timespec_to_ns(&ts);
/* TODO: Handle PTS and SCR. */
buf->state = UVC_BUF_STATE_ACTIVE;
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 27b4b9e..93e16375 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -119,8 +119,9 @@ static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
* and the timecode field and flag if needed.
*/
if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_COPY)
- vbuf->timestamp = b->timestamp;
+ V4L2_BUF_FLAG_TIMESTAMP_COPY) {
+ vb->timestamp = timeval_to_ns(&b->timestamp);
+ }
vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
if (b->flags & V4L2_BUF_FLAG_TIMECODE)
vbuf->timecode = b->timecode;
@@ -191,7 +192,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
b->flags = vbuf->flags;
b->field = vbuf->field;
- b->timestamp = vbuf->timestamp;
+ b->timestamp = ns_to_timeval(vb->timestamp);
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
b->reserved2 = 0;
@@ -308,8 +309,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
"for an output buffer\n");
return -EINVAL;
}
- vbuf->timestamp.tv_sec = 0;
- vbuf->timestamp.tv_usec = 0;
+ vb->timestamp = 0;
vbuf->sequence = 0;
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 0fdff91..d17e764 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -470,7 +470,7 @@ void vpfe_video_process_buffer_complete(struct vpfe_video_device *video)
{
struct vpfe_pipeline *pipe = &video->pipe;
- v4l2_get_timestamp(&video->cur_frm->vb.timestamp);
+ video->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&video->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
video->cur_frm = video->next_frm;
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index 28c067d..03447cc 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -435,7 +435,7 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
list_del(&buf->list);
spin_unlock_irqrestore(&video->qlock, flags);
- v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
/* Do frame number propagation only if this is the output video node.
* Frame number either comes from the CSI receivers or it gets
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index 51d4a17..af1e889 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -329,7 +329,7 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
buf->buf.field = V4L2_FIELD_NONE;
buf->buf.sequence = queue->sequence++;
- v4l2_get_timestamp(&buf->buf.timestamp);
+ buf->buf.vb2_buf.timestamp = ktime_get_ns();
vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 647ebfe..6404f81 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -211,6 +211,7 @@ struct vb2_queue;
* @num_planes: number of planes in the buffer
* on an internal driver queue
* @planes: private per-plane information; do not change
+ * @timestamp: frame timestamp
*/
struct vb2_buffer {
struct vb2_queue *vb2_queue;
@@ -219,6 +220,7 @@ struct vb2_buffer {
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VB2_MAX_PLANES];
+ u64 timestamp;
/* private: internal use only
*
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 5abab1e..110062e 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -28,7 +28,6 @@
* @vb2_buf: video buffer 2
* @flags: buffer informational flags
* @field: enum v4l2_field; field order of the image in the buffer
- * @timestamp: frame timestamp
* @timecode: frame timecode
* @sequence: sequence count of this frame
* Should contain enough information to be able to cover all the fields
@@ -39,7 +38,6 @@ struct vb2_v4l2_buffer {
__u32 flags;
__u32 field;
- struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index 22afa26..ee7754c 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -184,7 +184,7 @@ DECLARE_EVENT_CLASS(vb2_v4l2_event_class,
__field(int, minor)
__field(u32, flags)
__field(u32, field)
- __field(s64, timestamp)
+ __field(u64, timestamp)
__field(u32, timecode_type)
__field(u32, timecode_flags)
__field(u8, timecode_frames)
@@ -205,7 +205,7 @@ DECLARE_EVENT_CLASS(vb2_v4l2_event_class,
__entry->minor = owner ? owner->vdev->minor : -1;
__entry->flags = vbuf->flags;
__entry->field = vbuf->field;
- __entry->timestamp = timeval_to_ns(&vbuf->timestamp);
+ __entry->timestamp = vb->timestamp;
__entry->timecode_type = vbuf->timecode.type;
__entry->timecode_flags = vbuf->timecode.flags;
__entry->timecode_frames = vbuf->timecode.frames;
diff --git a/include/trace/events/vb2.h b/include/trace/events/vb2.h
index bfeceeb..c1a2241 100644
--- a/include/trace/events/vb2.h
+++ b/include/trace/events/vb2.h
@@ -18,6 +18,7 @@ DECLARE_EVENT_CLASS(vb2_event_class,
__field(u32, index)
__field(u32, type)
__field(u32, bytesused)
+ __field(u64, timestamp)
),
TP_fast_assign(
@@ -28,14 +29,16 @@ DECLARE_EVENT_CLASS(vb2_event_class,
__entry->index = vb->index;
__entry->type = vb->type;
__entry->bytesused = vb->planes[0].bytesused;
+ __entry->timestamp = vb->timestamp;
),
TP_printk("owner = %p, queued = %u, owned_by_drv = %d, index = %u, "
- "type = %u, bytesused = %u", __entry->owner,
+ "type = %u, bytesused = %u, timestamp = %llu", __entry->owner,
__entry->queued_count,
__entry->owned_by_drv_count,
__entry->index, __entry->type,
- __entry->bytesused
+ __entry->bytesused,
+ __entry->timestamp
)
)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 1/6] media: videobuf2: Move timestamp to vb2_buffer
2015-11-03 10:16 ` [RFC PATCH v9 1/6] media: videobuf2: Move timestamp to vb2_buffer Junghak Sung
@ 2015-11-04 12:28 ` Hans Verkuil
2015-11-05 3:12 ` Junghak Sung
0 siblings, 1 reply; 17+ messages in thread
From: Hans Verkuil @ 2015-11-04 12:28 UTC (permalink / raw)
To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/03/15 11:16, Junghak Sung wrote:
> Move timestamp from struct vb2_v4l2_buffer to struct vb2_buffer
> for common use, and change its type to u64 in order to handling
> y2038 problem. This patch also includes all device drivers' changes related to
> this restructuring.
>
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
<snip>
> diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
> index 1bd2fd4..61df3e4 100644
> --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
> +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
> @@ -531,8 +531,8 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
>
> if (!ret) {
> vbuf->sequence = solo_enc->sequence++;
> - vbuf->timestamp.tv_sec = vop_sec(vh);
> - vbuf->timestamp.tv_usec = vop_usec(vh);
> + vb->timestamp = ((u64) vop_sec(vh) * NSEC_PER_SEC) +
> + (vop_usec(vh) * NSEC_PER_USEC);
This is wrong. Just use ktime_get_ns() here. It is probably best to first make a
single patch to change the solo driver to use v4l2_get_timestamp(), then convert
that to ktime_get_ns() in this patch.
The problem is that the timestamp is taken from the mpeg header, and so it is
not a CLOCK_MONOTONIC timestamp as is signaled to the user. Never noticed this
before, but it is a solo driver bug.
>
> /* Check for motion flags */
> if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
> diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
> index 26df903..44b00b8 100644
> --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
> +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
> @@ -225,7 +225,7 @@ finish_buf:
> vb2_set_plane_payload(vb, 0,
> solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
> vbuf->sequence = solo_dev->sequence++;
> - v4l2_get_timestamp(&vbuf->timestamp);
> + vb->timestamp = ktime_get_ns();
> }
>
> vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
<snip>
> diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
> index 83cc6d3..b0ad054 100644
> --- a/drivers/media/platform/vivid/vivid-kthread-cap.c
> +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
> @@ -441,7 +441,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
> * "Start of Exposure".
> */
> if (dev->tstamp_src_is_soe)
> - v4l2_get_timestamp(&buf->vb.timestamp);
> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
> if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
> /*
> * 60 Hz standards start with the bottom field, 50 Hz standards
> @@ -558,8 +558,9 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
> * the timestamp now.
> */
> if (!dev->tstamp_src_is_soe)
> - v4l2_get_timestamp(&buf->vb.timestamp);
> - buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
> + buf->vb.vb2_buf.timestamp +=
> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
I'd do this differently: make time_wrap_offset of type u64 and assign it
accordingly with nanoseconds. That way you can just do:
timestamp += dev->time_wrap_offset
vivid-ctrls.c also needs to be modified (vivid_streaming_s_ctrl(), VIVID_CID_TIME_WRAP
case) to:
dev->time_wrap_offset = (0x100000000ULL - 16) * NSEC_PER_SEC - ktime_get_ns();
The v4l2_get_timestamp() call there can be dropped.
> }
>
> /*
> diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
> index c2c46dc..6fd02c9 100644
> --- a/drivers/media/platform/vivid/vivid-kthread-out.c
> +++ b/drivers/media/platform/vivid/vivid-kthread-out.c
> @@ -95,8 +95,9 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
> */
> vid_out_buf->vb.sequence /= 2;
> }
> - v4l2_get_timestamp(&vid_out_buf->vb.timestamp);
> - vid_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
> + vid_out_buf->vb.vb2_buf.timestamp = ktime_get_ns();
> + vid_out_buf->vb.vb2_buf.timestamp +=
> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
> vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ?
> VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
> dprintk(dev, 2, "vid_out buffer %d done\n",
> @@ -108,8 +109,9 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
> vivid_sliced_vbi_out_process(dev, vbi_out_buf);
>
> vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
> - v4l2_get_timestamp(&vbi_out_buf->vb.timestamp);
> - vbi_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
> + vbi_out_buf->vb.vb2_buf.timestamp = ktime_get_ns();
> + vbi_out_buf->vb.vb2_buf.timestamp +=
> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
> vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ?
> VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
> dprintk(dev, 2, "vbi_out buffer %d done\n",
> diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
> index 082c401..dbdb43d 100644
> --- a/drivers/media/platform/vivid/vivid-sdr-cap.c
> +++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
> @@ -117,8 +117,9 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
> if (sdr_cap_buf) {
> sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count;
> vivid_sdr_cap_process(dev, sdr_cap_buf);
> - v4l2_get_timestamp(&sdr_cap_buf->vb.timestamp);
> - sdr_cap_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
> + sdr_cap_buf->vb.vb2_buf.timestamp = ktime_get_ns();
> + sdr_cap_buf->vb.vb2_buf.timestamp +=
> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
> vb2_buffer_done(&sdr_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
> VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
> dev->dqbuf_error = false;
> diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
> index e903d02..2f5f330 100644
> --- a/drivers/media/platform/vivid/vivid-vbi-cap.c
> +++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
> @@ -108,8 +108,9 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
> if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode))
> vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
>
> - v4l2_get_timestamp(&buf->vb.timestamp);
> - buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
> + buf->vb.vb2_buf.timestamp +=
> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
> }
>
>
> @@ -133,8 +134,9 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
> vbuf[i] = dev->vbi_gen.data[i];
> }
>
> - v4l2_get_timestamp(&buf->vb.timestamp);
> - buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
> + buf->vb.vb2_buf.timestamp +=
> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
> }
>
> static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg,
<snip>
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 27b4b9e..93e16375 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -119,8 +119,9 @@ static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
> * and the timecode field and flag if needed.
> */
> if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> - V4L2_BUF_FLAG_TIMESTAMP_COPY)
> - vbuf->timestamp = b->timestamp;
> + V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> + vb->timestamp = timeval_to_ns(&b->timestamp);
> + }
No need to add {} for a one-line statement.
> vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> vbuf->timecode = b->timecode;
<snip>
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 647ebfe..6404f81 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -211,6 +211,7 @@ struct vb2_queue;
> * @num_planes: number of planes in the buffer
> * on an internal driver queue
> * @planes: private per-plane information; do not change
> + * @timestamp: frame timestamp
Please mention the unit (ns).
> */
> struct vb2_buffer {
> struct vb2_queue *vb2_queue;
> @@ -219,6 +220,7 @@ struct vb2_buffer {
> unsigned int memory;
> unsigned int num_planes;
> struct vb2_plane planes[VB2_MAX_PLANES];
> + u64 timestamp;
>
> /* private: internal use only
> *
Other than these minor issues it looks good.
Regards,
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 1/6] media: videobuf2: Move timestamp to vb2_buffer
2015-11-04 12:28 ` Hans Verkuil
@ 2015-11-05 3:12 ` Junghak Sung
2015-11-05 7:50 ` Hans Verkuil
0 siblings, 1 reply; 17+ messages in thread
From: Junghak Sung @ 2015-11-05 3:12 UTC (permalink / raw)
To: Hans Verkuil, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
Dear Hans,
First of all, thank you for your review.
On 11/04/2015 09:28 PM, Hans Verkuil wrote:
> On 11/03/15 11:16, Junghak Sung wrote:
>> Move timestamp from struct vb2_v4l2_buffer to struct vb2_buffer
>> for common use, and change its type to u64 in order to handling
>> y2038 problem. This patch also includes all device drivers' changes related to
>> this restructuring.
>>
>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> Acked-by: Inki Dae <inki.dae@samsung.com>
>> ---
>
> <snip>
>
>> diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
>> index 1bd2fd4..61df3e4 100644
>> --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
>> +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
>> @@ -531,8 +531,8 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
>>
>> if (!ret) {
>> vbuf->sequence = solo_enc->sequence++;
>> - vbuf->timestamp.tv_sec = vop_sec(vh);
>> - vbuf->timestamp.tv_usec = vop_usec(vh);
>> + vb->timestamp = ((u64) vop_sec(vh) * NSEC_PER_SEC) +
>> + (vop_usec(vh) * NSEC_PER_USEC);
>
> This is wrong. Just use ktime_get_ns() here. It is probably best to first make a
> single patch to change the solo driver to use v4l2_get_timestamp(), then convert
> that to ktime_get_ns() in this patch.
>
> The problem is that the timestamp is taken from the mpeg header, and so it is
> not a CLOCK_MONOTONIC timestamp as is signaled to the user. Never noticed this
> before, but it is a solo driver bug.
>
OK, I will prepare a single patch for solo driver to use
v4l2_get_timestamp(), and then converting to ktime_get_ns()
will be included in next version - v10.
I'm not aware of this historical problem.
so, it's very helpful. Thank you, Hans.
>>
>> /* Check for motion flags */
>> if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
>> diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
>> index 26df903..44b00b8 100644
>> --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
>> +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
>> @@ -225,7 +225,7 @@ finish_buf:
>> vb2_set_plane_payload(vb, 0,
>> solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
>> vbuf->sequence = solo_dev->sequence++;
>> - v4l2_get_timestamp(&vbuf->timestamp);
>> + vb->timestamp = ktime_get_ns();
>> }
>>
>> vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
>
> <snip>
>
>> diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
>> index 83cc6d3..b0ad054 100644
>> --- a/drivers/media/platform/vivid/vivid-kthread-cap.c
>> +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
>> @@ -441,7 +441,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
>> * "Start of Exposure".
>> */
>> if (dev->tstamp_src_is_soe)
>> - v4l2_get_timestamp(&buf->vb.timestamp);
>> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
>> /*
>> * 60 Hz standards start with the bottom field, 50 Hz standards
>> @@ -558,8 +558,9 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
>> * the timestamp now.
>> */
>> if (!dev->tstamp_src_is_soe)
>> - v4l2_get_timestamp(&buf->vb.timestamp);
>> - buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> + buf->vb.vb2_buf.timestamp +=
>> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
>
> I'd do this differently: make time_wrap_offset of type u64 and assign it
> accordingly with nanoseconds. That way you can just do:
>
> timestamp += dev->time_wrap_offset
>
> vivid-ctrls.c also needs to be modified (vivid_streaming_s_ctrl(), VIVID_CID_TIME_WRAP
> case) to:
>
> dev->time_wrap_offset = (0x100000000ULL - 16) * NSEC_PER_SEC - ktime_get_ns();
>
> The v4l2_get_timestamp() call there can be dropped.
>
I agree with your opinion. But it is too hard to read the code
getting time_wrap_offset.
How about this way?
in vivid_streaming_s_ctrl() of vivid-ctrls.c
dev->time_wrap_offset = ktime_get_ns() + 16 * NSEC_PER_SEC;
and in vivid_fillbuff() of vivid-kthread-cap.c
buf->vb.vb2_buf.timestamp -= dev->time_wrap_offset;
>> }
>>
>> /*
>> diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
>> index c2c46dc..6fd02c9 100644
>> --- a/drivers/media/platform/vivid/vivid-kthread-out.c
>> +++ b/drivers/media/platform/vivid/vivid-kthread-out.c
>> @@ -95,8 +95,9 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
>> */
>> vid_out_buf->vb.sequence /= 2;
>> }
>> - v4l2_get_timestamp(&vid_out_buf->vb.timestamp);
>> - vid_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>> + vid_out_buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> + vid_out_buf->vb.vb2_buf.timestamp +=
>> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
>> vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ?
>> VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
>> dprintk(dev, 2, "vid_out buffer %d done\n",
>> @@ -108,8 +109,9 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
>> vivid_sliced_vbi_out_process(dev, vbi_out_buf);
>>
>> vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
>> - v4l2_get_timestamp(&vbi_out_buf->vb.timestamp);
>> - vbi_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>> + vbi_out_buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> + vbi_out_buf->vb.vb2_buf.timestamp +=
>> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
>> vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ?
>> VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
>> dprintk(dev, 2, "vbi_out buffer %d done\n",
>> diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
>> index 082c401..dbdb43d 100644
>> --- a/drivers/media/platform/vivid/vivid-sdr-cap.c
>> +++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
>> @@ -117,8 +117,9 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
>> if (sdr_cap_buf) {
>> sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count;
>> vivid_sdr_cap_process(dev, sdr_cap_buf);
>> - v4l2_get_timestamp(&sdr_cap_buf->vb.timestamp);
>> - sdr_cap_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>> + sdr_cap_buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> + sdr_cap_buf->vb.vb2_buf.timestamp +=
>> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
>> vb2_buffer_done(&sdr_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
>> VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
>> dev->dqbuf_error = false;
>> diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
>> index e903d02..2f5f330 100644
>> --- a/drivers/media/platform/vivid/vivid-vbi-cap.c
>> +++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
>> @@ -108,8 +108,9 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
>> if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode))
>> vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
>>
>> - v4l2_get_timestamp(&buf->vb.timestamp);
>> - buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> + buf->vb.vb2_buf.timestamp +=
>> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
>> }
>>
>>
>> @@ -133,8 +134,9 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
>> vbuf[i] = dev->vbi_gen.data[i];
>> }
>>
>> - v4l2_get_timestamp(&buf->vb.timestamp);
>> - buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> + buf->vb.vb2_buf.timestamp +=
>> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
>> }
>>
>> static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg,
>
> <snip>
>
>> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> index 27b4b9e..93e16375 100644
>> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
>> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> @@ -119,8 +119,9 @@ static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
>> * and the timecode field and flag if needed.
>> */
>> if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> - V4L2_BUF_FLAG_TIMESTAMP_COPY)
>> - vbuf->timestamp = b->timestamp;
>> + V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> + vb->timestamp = timeval_to_ns(&b->timestamp);
>> + }
>
> No need to add {} for a one-line statement.
>
OK, I'll fix it.
>> vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>> if (b->flags & V4L2_BUF_FLAG_TIMECODE)
>> vbuf->timecode = b->timecode;
>
> <snip>
>
>> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
>> index 647ebfe..6404f81 100644
>> --- a/include/media/videobuf2-core.h
>> +++ b/include/media/videobuf2-core.h
>> @@ -211,6 +211,7 @@ struct vb2_queue;
>> * @num_planes: number of planes in the buffer
>> * on an internal driver queue
>> * @planes: private per-plane information; do not change
>> + * @timestamp: frame timestamp
>
> Please mention the unit (ns).
>
OK, I'll fix it.
Best regards,
Junghak
>> */
>> struct vb2_buffer {
>> struct vb2_queue *vb2_queue;
>> @@ -219,6 +220,7 @@ struct vb2_buffer {
>> unsigned int memory;
>> unsigned int num_planes;
>> struct vb2_plane planes[VB2_MAX_PLANES];
>> + u64 timestamp;
>>
>> /* private: internal use only
>> *
>
> Other than these minor issues it looks good.
>
> Regards,
>
> Hans
>
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 1/6] media: videobuf2: Move timestamp to vb2_buffer
2015-11-05 3:12 ` Junghak Sung
@ 2015-11-05 7:50 ` Hans Verkuil
0 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2015-11-05 7:50 UTC (permalink / raw)
To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/05/2015 04:12 AM, Junghak Sung wrote:
>>> diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
>>> index 83cc6d3..b0ad054 100644
>>> --- a/drivers/media/platform/vivid/vivid-kthread-cap.c
>>> +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
>>> @@ -441,7 +441,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
>>> * "Start of Exposure".
>>> */
>>> if (dev->tstamp_src_is_soe)
>>> - v4l2_get_timestamp(&buf->vb.timestamp);
>>> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
>>> if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
>>> /*
>>> * 60 Hz standards start with the bottom field, 50 Hz standards
>>> @@ -558,8 +558,9 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
>>> * the timestamp now.
>>> */
>>> if (!dev->tstamp_src_is_soe)
>>> - v4l2_get_timestamp(&buf->vb.timestamp);
>>> - buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>>> + buf->vb.vb2_buf.timestamp = ktime_get_ns();
>>> + buf->vb.vb2_buf.timestamp +=
>>> + ((u64) dev->time_wrap_offset * NSEC_PER_SEC);
>>
>> I'd do this differently: make time_wrap_offset of type u64 and assign it
>> accordingly with nanoseconds. That way you can just do:
>>
>> timestamp += dev->time_wrap_offset
>>
>> vivid-ctrls.c also needs to be modified (vivid_streaming_s_ctrl(), VIVID_CID_TIME_WRAP
>> case) to:
>>
>> dev->time_wrap_offset = (0x100000000ULL - 16) * NSEC_PER_SEC - ktime_get_ns();
>>
>> The v4l2_get_timestamp() call there can be dropped.
>>
>
> I agree with your opinion. But it is too hard to read the code
> getting time_wrap_offset.
> How about this way?
>
> in vivid_streaming_s_ctrl() of vivid-ctrls.c
> dev->time_wrap_offset = ktime_get_ns() + 16 * NSEC_PER_SEC;
> and in vivid_fillbuff() of vivid-kthread-cap.c
> buf->vb.vb2_buf.timestamp -= dev->time_wrap_offset;
That doesn't do what I want it to do, which is to wrap around in the struct timeval
where seconds are 32 bits. The code above is actually wrong since I forgot that
tv_sec in struct timeval is signed, so 0x100000000ULL should be 0x80000000ULL.
Also, that code will fail after 2038, so that's no good either.
On a related note I send out a question to Arnd whether a timestamp should be u64
or s64. It's not clear to me which should be used as ktime_get_ns() returns a s64.
Once we return the full 64 bits to userspace, then we have a second wrap around when
the u64 (or s64) wraps. I'll add a second wrap-around control to vivid at that time.
I'll wait for Arnd to answer before fixing the time_wrap_offset calculation since I
need to know whether a timestamp is u64 or s64.
Regards,
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC PATCH v9 2/6] media: videobuf2: Add set_timestamp to struct vb2_queue
2015-11-03 10:16 [RFC PATCH v9] Refactoring Videobuf2 for common use Junghak Sung
2015-11-03 10:16 ` [RFC PATCH v9 1/6] media: videobuf2: Move timestamp to vb2_buffer Junghak Sung
@ 2015-11-03 10:16 ` Junghak Sung
2015-11-04 12:41 ` Hans Verkuil
2015-11-03 10:16 ` [RFC PATCH v9 3/6] media: videobuf2: Separate vb2_poll() Junghak Sung
` (3 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Junghak Sung @ 2015-11-03 10:16 UTC (permalink / raw)
To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus,
pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
Junghak Sung
Add set_timestamp to struct vb2_queue as a flag set if vb2-core should
set timestamps.
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
drivers/media/v4l2-core/videobuf2-v4l2.c | 20 +++++++-------------
include/media/videobuf2-core.h | 2 ++
2 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 93e16375..d254452 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -118,10 +118,8 @@ static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
* For output buffers copy the timestamp if needed,
* and the timecode field and flag if needed.
*/
- if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_COPY) {
+ if (q->set_timestamp)
vb->timestamp = timeval_to_ns(&b->timestamp);
- }
vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
if (b->flags & V4L2_BUF_FLAG_TIMECODE)
vbuf->timecode = b->timecode;
@@ -239,8 +237,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
*/
b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
- if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
- V4L2_BUF_FLAG_TIMESTAMP_COPY) {
+ if (!q->set_timestamp) {
/*
* For non-COPY timestamps, drop timestamp source bits
* and obtain the timestamp source from the queue.
@@ -404,8 +401,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
/* Zero flags that the vb2 core handles */
vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
- if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
- V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
+ if (!vb->vb2_queue->set_timestamp || !V4L2_TYPE_IS_OUTPUT(b->type)) {
/*
* Non-COPY timestamps and non-OUTPUT queues will get
* their timestamp and timestamp source flags from the
@@ -723,6 +719,8 @@ int vb2_queue_init(struct vb2_queue *q)
q->buf_ops = &v4l2_buf_ops;
q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
+ q->set_timestamp = (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK)
+ == V4L2_BUF_FLAG_TIMESTAMP_COPY;
return vb2_core_queue_init(q);
}
@@ -1080,9 +1078,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
* should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
* else is able to provide this information with the write() operation.
*/
- bool set_timestamp = !read &&
- (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ bool set_timestamp = !read && q->set_timestamp;
int ret, index;
dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
@@ -1271,9 +1267,7 @@ static int vb2_thread(void *data)
if (q->is_output) {
prequeue = q->num_buffers;
- set_timestamp =
- (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
- V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ set_timestamp = q->set_timestamp;
}
set_freezable();
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 6404f81..b73a28a 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -431,6 +431,7 @@ struct vb2_buf_ops {
* called since poll() needs to return POLLERR in that situation.
* @is_multiplanar: set if buffer type is multiplanar
* @is_output: set if buffer type is output
+ * @copy_timestamp: set if vb2-core should set timestamps
* @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
* last decoded buffer was already dequeued. Set for capture queues
* when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
@@ -480,6 +481,7 @@ struct vb2_queue {
unsigned int waiting_for_buffers:1;
unsigned int is_multiplanar:1;
unsigned int is_output:1;
+ unsigned int set_timestamp:1;
unsigned int last_buffer_dequeued:1;
struct vb2_fileio_data *fileio;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 2/6] media: videobuf2: Add set_timestamp to struct vb2_queue
2015-11-03 10:16 ` [RFC PATCH v9 2/6] media: videobuf2: Add set_timestamp to struct vb2_queue Junghak Sung
@ 2015-11-04 12:41 ` Hans Verkuil
2015-11-05 3:19 ` Junghak Sung
0 siblings, 1 reply; 17+ messages in thread
From: Hans Verkuil @ 2015-11-04 12:41 UTC (permalink / raw)
To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/03/15 11:16, Junghak Sung wrote:
> Add set_timestamp to struct vb2_queue as a flag set if vb2-core should
> set timestamps.
>
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
> drivers/media/v4l2-core/videobuf2-v4l2.c | 20 +++++++-------------
> include/media/videobuf2-core.h | 2 ++
> 2 files changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 93e16375..d254452 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -118,10 +118,8 @@ static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
> * For output buffers copy the timestamp if needed,
> * and the timecode field and flag if needed.
> */
> - if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> - V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> + if (q->set_timestamp)
> vb->timestamp = timeval_to_ns(&b->timestamp);
> - }
> vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> vbuf->timecode = b->timecode;
> @@ -239,8 +237,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
> */
> b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> - if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> - V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> + if (!q->set_timestamp) {
> /*
> * For non-COPY timestamps, drop timestamp source bits
> * and obtain the timestamp source from the queue.
> @@ -404,8 +401,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
>
> /* Zero flags that the vb2 core handles */
> vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> - if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> - V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
> + if (!vb->vb2_queue->set_timestamp || !V4L2_TYPE_IS_OUTPUT(b->type)) {
> /*
> * Non-COPY timestamps and non-OUTPUT queues will get
> * their timestamp and timestamp source flags from the
> @@ -723,6 +719,8 @@ int vb2_queue_init(struct vb2_queue *q)
> q->buf_ops = &v4l2_buf_ops;
> q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
> + q->set_timestamp = (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK)
> + == V4L2_BUF_FLAG_TIMESTAMP_COPY;
>
> return vb2_core_queue_init(q);
> }
> @@ -1080,9 +1078,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
> * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
> * else is able to provide this information with the write() operation.
> */
> - bool set_timestamp = !read &&
> - (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> - V4L2_BUF_FLAG_TIMESTAMP_COPY;
> + bool set_timestamp = !read && q->set_timestamp;
> int ret, index;
>
> dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
> @@ -1271,9 +1267,7 @@ static int vb2_thread(void *data)
>
> if (q->is_output) {
> prequeue = q->num_buffers;
> - set_timestamp =
> - (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> - V4L2_BUF_FLAG_TIMESTAMP_COPY;
> + set_timestamp = q->set_timestamp;
> }
>
> set_freezable();
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 6404f81..b73a28a 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -431,6 +431,7 @@ struct vb2_buf_ops {
> * called since poll() needs to return POLLERR in that situation.
> * @is_multiplanar: set if buffer type is multiplanar
> * @is_output: set if buffer type is output
> + * @copy_timestamp: set if vb2-core should set timestamps
This says copy_timestamp,
> * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
> * last decoded buffer was already dequeued. Set for capture queues
> * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
> @@ -480,6 +481,7 @@ struct vb2_queue {
> unsigned int waiting_for_buffers:1;
> unsigned int is_multiplanar:1;
> unsigned int is_output:1;
> + unsigned int set_timestamp:1;
while this is set_timestamp.
I actually think the comment is right and this field should be called
copy_timestamp. The timestamp is never actually set, it is just copied.
> unsigned int last_buffer_dequeued:1;
>
> struct vb2_fileio_data *fileio;
>
Regards,
Hams
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 2/6] media: videobuf2: Add set_timestamp to struct vb2_queue
2015-11-04 12:41 ` Hans Verkuil
@ 2015-11-05 3:19 ` Junghak Sung
0 siblings, 0 replies; 17+ messages in thread
From: Junghak Sung @ 2015-11-05 3:19 UTC (permalink / raw)
To: Hans Verkuil, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/04/2015 09:41 PM, Hans Verkuil wrote:
> On 11/03/15 11:16, Junghak Sung wrote:
>> Add set_timestamp to struct vb2_queue as a flag set if vb2-core should
>> set timestamps.
>>
>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> Acked-by: Inki Dae <inki.dae@samsung.com>
>> ---
>> drivers/media/v4l2-core/videobuf2-v4l2.c | 20 +++++++-------------
>> include/media/videobuf2-core.h | 2 ++
>> 2 files changed, 9 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> index 93e16375..d254452 100644
>> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
>> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> @@ -118,10 +118,8 @@ static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
>> * For output buffers copy the timestamp if needed,
>> * and the timecode field and flag if needed.
>> */
>> - if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> - V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> + if (q->set_timestamp)
>> vb->timestamp = timeval_to_ns(&b->timestamp);
>> - }
>> vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>> if (b->flags & V4L2_BUF_FLAG_TIMECODE)
>> vbuf->timecode = b->timecode;
>> @@ -239,8 +237,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
>> */
>> b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>> b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>> - if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> - V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> + if (!q->set_timestamp) {
>> /*
>> * For non-COPY timestamps, drop timestamp source bits
>> * and obtain the timestamp source from the queue.
>> @@ -404,8 +401,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
>>
>> /* Zero flags that the vb2 core handles */
>> vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>> - if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> - V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
>> + if (!vb->vb2_queue->set_timestamp || !V4L2_TYPE_IS_OUTPUT(b->type)) {
>> /*
>> * Non-COPY timestamps and non-OUTPUT queues will get
>> * their timestamp and timestamp source flags from the
>> @@ -723,6 +719,8 @@ int vb2_queue_init(struct vb2_queue *q)
>> q->buf_ops = &v4l2_buf_ops;
>> q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
>> q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
>> + q->set_timestamp = (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK)
>> + == V4L2_BUF_FLAG_TIMESTAMP_COPY;
>>
>> return vb2_core_queue_init(q);
>> }
>> @@ -1080,9 +1078,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>> * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
>> * else is able to provide this information with the write() operation.
>> */
>> - bool set_timestamp = !read &&
>> - (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> - V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> + bool set_timestamp = !read && q->set_timestamp;
>> int ret, index;
>>
>> dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
>> @@ -1271,9 +1267,7 @@ static int vb2_thread(void *data)
>>
>> if (q->is_output) {
>> prequeue = q->num_buffers;
>> - set_timestamp =
>> - (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> - V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> + set_timestamp = q->set_timestamp;
>> }
>>
>> set_freezable();
>> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
>> index 6404f81..b73a28a 100644
>> --- a/include/media/videobuf2-core.h
>> +++ b/include/media/videobuf2-core.h
>> @@ -431,6 +431,7 @@ struct vb2_buf_ops {
>> * called since poll() needs to return POLLERR in that situation.
>> * @is_multiplanar: set if buffer type is multiplanar
>> * @is_output: set if buffer type is output
>> + * @copy_timestamp: set if vb2-core should set timestamps
>
> This says copy_timestamp,
>
>> * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
>> * last decoded buffer was already dequeued. Set for capture queues
>> * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
>> @@ -480,6 +481,7 @@ struct vb2_queue {
>> unsigned int waiting_for_buffers:1;
>> unsigned int is_multiplanar:1;
>> unsigned int is_output:1;
>> + unsigned int set_timestamp:1;
>
> while this is set_timestamp.
>
> I actually think the comment is right and this field should be called
> copy_timestamp. The timestamp is never actually set, it is just copied.
>
OK, copy_timestamp would be better name from your review.
Thank you, Hans.
Best regards,
Junghak
>> unsigned int last_buffer_dequeued:1;
>>
>> struct vb2_fileio_data *fileio;
>>
>
> Regards,
>
> Hams
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC PATCH v9 3/6] media: videobuf2: Separate vb2_poll()
2015-11-03 10:16 [RFC PATCH v9] Refactoring Videobuf2 for common use Junghak Sung
2015-11-03 10:16 ` [RFC PATCH v9 1/6] media: videobuf2: Move timestamp to vb2_buffer Junghak Sung
2015-11-03 10:16 ` [RFC PATCH v9 2/6] media: videobuf2: Add set_timestamp to struct vb2_queue Junghak Sung
@ 2015-11-03 10:16 ` Junghak Sung
2015-11-05 9:55 ` Hans Verkuil
2015-11-03 10:16 ` [RFC PATCH v9 4/6] media: videobuf2: last_buffer_queued is set at fill_v4l2_buffer() Junghak Sung
` (2 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Junghak Sung @ 2015-11-03 10:16 UTC (permalink / raw)
To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus,
pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
Junghak Sung
Separate vb2_poll() into core and v4l2 part.
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
drivers/media/v4l2-core/videobuf2-v4l2.c | 80 +++++++++++++++++++-----------
1 file changed, 52 insertions(+), 28 deletions(-)
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index d254452..0ca9f23 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -745,7 +745,7 @@ void vb2_queue_release(struct vb2_queue *q)
EXPORT_SYMBOL_GPL(vb2_queue_release);
/**
- * vb2_poll() - implements poll userspace operation
+ * vb2_core_poll() - implements poll userspace operation
* @q: videobuf2 queue
* @file: file argument passed to the poll file operation handler
* @wait: wait argument passed to the poll file operation handler
@@ -757,33 +757,20 @@ EXPORT_SYMBOL_GPL(vb2_queue_release);
* For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
* will be reported as available for writing.
*
- * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
- * pending events.
- *
* The return values from this function are intended to be directly returned
* from poll handler in driver.
*/
-unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
+unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file,
+ poll_table *wait)
{
- struct video_device *vfd = video_devdata(file);
unsigned long req_events = poll_requested_events(wait);
struct vb2_buffer *vb = NULL;
- unsigned int res = 0;
unsigned long flags;
- if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
- struct v4l2_fh *fh = file->private_data;
-
- if (v4l2_event_pending(fh))
- res = POLLPRI;
- else if (req_events & POLLPRI)
- poll_wait(file, &fh->wait, wait);
- }
-
if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
- return res;
+ return 0;
if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
- return res;
+ return 0;
/*
* Start file I/O emulator only if streaming API has not been used yet.
@@ -792,16 +779,16 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
if (!q->is_output && (q->io_modes & VB2_READ) &&
(req_events & (POLLIN | POLLRDNORM))) {
if (__vb2_init_fileio(q, 1))
- return res | POLLERR;
+ return POLLERR;
}
if (q->is_output && (q->io_modes & VB2_WRITE) &&
(req_events & (POLLOUT | POLLWRNORM))) {
if (__vb2_init_fileio(q, 0))
- return res | POLLERR;
+ return POLLERR;
/*
* Write to OUTPUT queue can be done immediately.
*/
- return res | POLLOUT | POLLWRNORM;
+ return POLLOUT | POLLWRNORM;
}
}
@@ -810,21 +797,21 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
* error flag is set.
*/
if (!vb2_is_streaming(q) || q->error)
- return res | POLLERR;
+ return POLLERR;
/*
* For compatibility with vb1: if QBUF hasn't been called yet, then
* return POLLERR as well. This only affects capture queues, output
* queues will always initialize waiting_for_buffers to false.
*/
if (q->waiting_for_buffers)
- return res | POLLERR;
+ return POLLERR;
/*
* For output streams you can write as long as there are fewer buffers
* queued than there are buffers available.
*/
if (q->is_output && q->queued_count < q->num_buffers)
- return res | POLLOUT | POLLWRNORM;
+ return POLLOUT | POLLWRNORM;
if (list_empty(&q->done_list)) {
/*
@@ -832,7 +819,7 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
* return immediately. DQBUF will return -EPIPE.
*/
if (q->last_buffer_dequeued)
- return res | POLLIN | POLLRDNORM;
+ return POLLIN | POLLRDNORM;
poll_wait(file, &q->done_wq, wait);
}
@@ -849,10 +836,47 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
if (vb && (vb->state == VB2_BUF_STATE_DONE
|| vb->state == VB2_BUF_STATE_ERROR)) {
return (q->is_output) ?
- res | POLLOUT | POLLWRNORM :
- res | POLLIN | POLLRDNORM;
+ POLLOUT | POLLWRNORM :
+ POLLIN | POLLRDNORM;
}
- return res;
+ return 0;
+}
+
+/**
+ * vb2_poll() - implements poll userspace operation
+ * @q: videobuf2 queue
+ * @file: file argument passed to the poll file operation handler
+ * @wait: wait argument passed to the poll file operation handler
+ *
+ * This function implements poll file operation handler for a driver.
+ * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
+ * be informed that the file descriptor of a video device is available for
+ * reading.
+ * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
+ * will be reported as available for writing.
+ *
+ * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
+ * pending events.
+ *
+ * The return values from this function are intended to be directly returned
+ * from poll handler in driver.
+ */
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
+{
+ struct video_device *vfd = video_devdata(file);
+ unsigned long req_events = poll_requested_events(wait);
+ unsigned int res = 0;
+
+ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+ struct v4l2_fh *fh = file->private_data;
+
+ if (v4l2_event_pending(fh))
+ res = POLLPRI;
+ else if (req_events & POLLPRI)
+ poll_wait(file, &fh->wait, wait);
+ }
+
+ return res | vb2_core_poll(q, file, wait);
}
EXPORT_SYMBOL_GPL(vb2_poll);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 3/6] media: videobuf2: Separate vb2_poll()
2015-11-03 10:16 ` [RFC PATCH v9 3/6] media: videobuf2: Separate vb2_poll() Junghak Sung
@ 2015-11-05 9:55 ` Hans Verkuil
0 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2015-11-05 9:55 UTC (permalink / raw)
To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
Hi Junghak,
One comment below:
On 11/03/15 11:16, Junghak Sung wrote:
> Separate vb2_poll() into core and v4l2 part.
>
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
> drivers/media/v4l2-core/videobuf2-v4l2.c | 80 +++++++++++++++++++-----------
> 1 file changed, 52 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index d254452..0ca9f23 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -745,7 +745,7 @@ void vb2_queue_release(struct vb2_queue *q)
> EXPORT_SYMBOL_GPL(vb2_queue_release);
>
> /**
> - * vb2_poll() - implements poll userspace operation
> + * vb2_core_poll() - implements poll userspace operation
> * @q: videobuf2 queue
> * @file: file argument passed to the poll file operation handler
> * @wait: wait argument passed to the poll file operation handler
> @@ -757,33 +757,20 @@ EXPORT_SYMBOL_GPL(vb2_queue_release);
> * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> * will be reported as available for writing.
> *
> - * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> - * pending events.
> - *
> * The return values from this function are intended to be directly returned
> * from poll handler in driver.
> */
> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> +unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file,
> + poll_table *wait)
> {
> - struct video_device *vfd = video_devdata(file);
> unsigned long req_events = poll_requested_events(wait);
> struct vb2_buffer *vb = NULL;
> - unsigned int res = 0;
> unsigned long flags;
>
> - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> - struct v4l2_fh *fh = file->private_data;
> -
> - if (v4l2_event_pending(fh))
> - res = POLLPRI;
> - else if (req_events & POLLPRI)
> - poll_wait(file, &fh->wait, wait);
> - }
> -
> if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
> - return res;
> + return 0;
> if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
> - return res;
> + return 0;
>
> /*
> * Start file I/O emulator only if streaming API has not been used yet.
> @@ -792,16 +779,16 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> if (!q->is_output && (q->io_modes & VB2_READ) &&
> (req_events & (POLLIN | POLLRDNORM))) {
> if (__vb2_init_fileio(q, 1))
> - return res | POLLERR;
> + return POLLERR;
> }
> if (q->is_output && (q->io_modes & VB2_WRITE) &&
> (req_events & (POLLOUT | POLLWRNORM))) {
> if (__vb2_init_fileio(q, 0))
> - return res | POLLERR;
> + return POLLERR;
> /*
> * Write to OUTPUT queue can be done immediately.
> */
> - return res | POLLOUT | POLLWRNORM;
> + return POLLOUT | POLLWRNORM;
> }
> }
>
> @@ -810,21 +797,21 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> * error flag is set.
> */
> if (!vb2_is_streaming(q) || q->error)
> - return res | POLLERR;
> + return POLLERR;
> /*
> * For compatibility with vb1: if QBUF hasn't been called yet, then
> * return POLLERR as well. This only affects capture queues, output
> * queues will always initialize waiting_for_buffers to false.
> */
> if (q->waiting_for_buffers)
> - return res | POLLERR;
> + return POLLERR;
This check is V4L2 specific (as discussed during the workshop) and it should either
be moved to vb2_poll (not sure if that is possible), or q->waiting_for_buffers
should only be set to true in the vb2-v4l2 part, or something like that.
>
> /*
> * For output streams you can write as long as there are fewer buffers
> * queued than there are buffers available.
> */
> if (q->is_output && q->queued_count < q->num_buffers)
> - return res | POLLOUT | POLLWRNORM;
> + return POLLOUT | POLLWRNORM;
>
> if (list_empty(&q->done_list)) {
> /*
> @@ -832,7 +819,7 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> * return immediately. DQBUF will return -EPIPE.
> */
> if (q->last_buffer_dequeued)
> - return res | POLLIN | POLLRDNORM;
> + return POLLIN | POLLRDNORM;
>
> poll_wait(file, &q->done_wq, wait);
> }
> @@ -849,10 +836,47 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> if (vb && (vb->state == VB2_BUF_STATE_DONE
> || vb->state == VB2_BUF_STATE_ERROR)) {
> return (q->is_output) ?
> - res | POLLOUT | POLLWRNORM :
> - res | POLLIN | POLLRDNORM;
> + POLLOUT | POLLWRNORM :
> + POLLIN | POLLRDNORM;
> }
> - return res;
> + return 0;
> +}
> +
> +/**
> + * vb2_poll() - implements poll userspace operation
> + * @q: videobuf2 queue
> + * @file: file argument passed to the poll file operation handler
> + * @wait: wait argument passed to the poll file operation handler
> + *
> + * This function implements poll file operation handler for a driver.
> + * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
> + * be informed that the file descriptor of a video device is available for
> + * reading.
> + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> + * will be reported as available for writing.
> + *
> + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> + * pending events.
> + *
> + * The return values from this function are intended to be directly returned
> + * from poll handler in driver.
> + */
> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> +{
> + struct video_device *vfd = video_devdata(file);
> + unsigned long req_events = poll_requested_events(wait);
> + unsigned int res = 0;
> +
> + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> + struct v4l2_fh *fh = file->private_data;
> +
> + if (v4l2_event_pending(fh))
> + res = POLLPRI;
> + else if (req_events & POLLPRI)
> + poll_wait(file, &fh->wait, wait);
> + }
> +
> + return res | vb2_core_poll(q, file, wait);
> }
> EXPORT_SYMBOL_GPL(vb2_poll);
>
>
Regards,
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC PATCH v9 4/6] media: videobuf2: last_buffer_queued is set at fill_v4l2_buffer()
2015-11-03 10:16 [RFC PATCH v9] Refactoring Videobuf2 for common use Junghak Sung
` (2 preceding siblings ...)
2015-11-03 10:16 ` [RFC PATCH v9 3/6] media: videobuf2: Separate vb2_poll() Junghak Sung
@ 2015-11-03 10:16 ` Junghak Sung
2015-11-05 10:00 ` Hans Verkuil
2015-11-03 10:16 ` [RFC PATCH v9 5/6] media: videobuf2: Refactor vb2_fileio_data and vb2_thread Junghak Sung
2015-11-03 10:16 ` [RFC PATCH v9 6/6] media: videobuf2: Move vb2_fileio_data and vb2_thread to core part Junghak Sung
5 siblings, 1 reply; 17+ messages in thread
From: Junghak Sung @ 2015-11-03 10:16 UTC (permalink / raw)
To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus,
pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
Junghak Sung
The location in which last_buffer_queued is set is moved to fill_v4l2_buffer().
So, __vb2_perform_fileio() can use vb2_core_dqbuf() instead of
vb2_internal_dqbuf().
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
drivers/media/v4l2-core/videobuf2-v4l2.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 0ca9f23..b0293df 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -270,6 +270,11 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
if (vb2_buffer_in_use(q, vb))
b->flags |= V4L2_BUF_FLAG_MAPPED;
+ if (!q->is_output &&
+ b->flags & V4L2_BUF_FLAG_DONE &&
+ b->flags & V4L2_BUF_FLAG_LAST)
+ q->last_buffer_dequeued = true;
+
return 0;
}
@@ -579,10 +584,6 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
ret = vb2_core_dqbuf(q, b, nonblocking);
- if (!ret && !q->is_output &&
- b->flags & V4L2_BUF_FLAG_LAST)
- q->last_buffer_dequeued = true;
-
return ret;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 4/6] media: videobuf2: last_buffer_queued is set at fill_v4l2_buffer()
2015-11-03 10:16 ` [RFC PATCH v9 4/6] media: videobuf2: last_buffer_queued is set at fill_v4l2_buffer() Junghak Sung
@ 2015-11-05 10:00 ` Hans Verkuil
2015-11-09 7:48 ` Junghak Sung
0 siblings, 1 reply; 17+ messages in thread
From: Hans Verkuil @ 2015-11-05 10:00 UTC (permalink / raw)
To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/03/15 11:16, Junghak Sung wrote:
> The location in which last_buffer_queued is set is moved to fill_v4l2_buffer().
> So, __vb2_perform_fileio() can use vb2_core_dqbuf() instead of
> vb2_internal_dqbuf().
>
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
One comment: I think the struct vb2_buf_ops callbacks can all return void
instead of int. I don't think they should ever be allowed to fail.
If you agree, then that can be changed in a separate later.
Regards,
Hans
> ---
> drivers/media/v4l2-core/videobuf2-v4l2.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 0ca9f23..b0293df 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -270,6 +270,11 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
> if (vb2_buffer_in_use(q, vb))
> b->flags |= V4L2_BUF_FLAG_MAPPED;
>
> + if (!q->is_output &&
> + b->flags & V4L2_BUF_FLAG_DONE &&
> + b->flags & V4L2_BUF_FLAG_LAST)
> + q->last_buffer_dequeued = true;
> +
> return 0;
> }
>
> @@ -579,10 +584,6 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>
> ret = vb2_core_dqbuf(q, b, nonblocking);
>
> - if (!ret && !q->is_output &&
> - b->flags & V4L2_BUF_FLAG_LAST)
> - q->last_buffer_dequeued = true;
> -
> return ret;
> }
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH v9 4/6] media: videobuf2: last_buffer_queued is set at fill_v4l2_buffer()
2015-11-05 10:00 ` Hans Verkuil
@ 2015-11-09 7:48 ` Junghak Sung
0 siblings, 0 replies; 17+ messages in thread
From: Junghak Sung @ 2015-11-09 7:48 UTC (permalink / raw)
To: Hans Verkuil, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/05/2015 07:00 PM, Hans Verkuil wrote:
> On 11/03/15 11:16, Junghak Sung wrote:
>> The location in which last_buffer_queued is set is moved to fill_v4l2_buffer().
>> So, __vb2_perform_fileio() can use vb2_core_dqbuf() instead of
>> vb2_internal_dqbuf().
>>
>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> Acked-by: Inki Dae <inki.dae@samsung.com>
>
> Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
>
> One comment: I think the struct vb2_buf_ops callbacks can all return void
> instead of int. I don't think they should ever be allowed to fail.
>
> If you agree, then that can be changed in a separate later.
>
Dear Hans,
IMHO, it seems to be better that vb2_buf_ops callbacks return int
as it is. Because fill_vb2_buffer() includes verifying the bytesused
value for each plane and checking ALTERNATE field for output buffer.
It can return fail if the information provided in a v4l2_buffer
by the userspace is not proper.
Best regards,
Junghak
> Regards,
>
> Hans
>
>> ---
>> drivers/media/v4l2-core/videobuf2-v4l2.c | 9 +++++----
>> 1 file changed, 5 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> index 0ca9f23..b0293df 100644
>> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
>> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> @@ -270,6 +270,11 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
>> if (vb2_buffer_in_use(q, vb))
>> b->flags |= V4L2_BUF_FLAG_MAPPED;
>>
>> + if (!q->is_output &&
>> + b->flags & V4L2_BUF_FLAG_DONE &&
>> + b->flags & V4L2_BUF_FLAG_LAST)
>> + q->last_buffer_dequeued = true;
>> +
>> return 0;
>> }
>>
>> @@ -579,10 +584,6 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>>
>> ret = vb2_core_dqbuf(q, b, nonblocking);
>>
>> - if (!ret && !q->is_output &&
>> - b->flags & V4L2_BUF_FLAG_LAST)
>> - q->last_buffer_dequeued = true;
>> -
>> return ret;
>> }
>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC PATCH v9 5/6] media: videobuf2: Refactor vb2_fileio_data and vb2_thread
2015-11-03 10:16 [RFC PATCH v9] Refactoring Videobuf2 for common use Junghak Sung
` (3 preceding siblings ...)
2015-11-03 10:16 ` [RFC PATCH v9 4/6] media: videobuf2: last_buffer_queued is set at fill_v4l2_buffer() Junghak Sung
@ 2015-11-03 10:16 ` Junghak Sung
2015-11-05 11:10 ` Hans Verkuil
2015-11-03 10:16 ` [RFC PATCH v9 6/6] media: videobuf2: Move vb2_fileio_data and vb2_thread to core part Junghak Sung
5 siblings, 1 reply; 17+ messages in thread
From: Junghak Sung @ 2015-11-03 10:16 UTC (permalink / raw)
To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus,
pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
Junghak Sung
Replace v4l2-stuffs with common things in struct vb2_fileio_data and
vb2_thread().
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
drivers/media/v4l2-core/videobuf2-v4l2.c | 104 ++++++++++++++----------------
1 file changed, 49 insertions(+), 55 deletions(-)
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index b0293df..f806ef4 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -920,9 +920,10 @@ struct vb2_fileio_buf {
* or write function.
*/
struct vb2_fileio_data {
- struct v4l2_requestbuffers req;
- struct v4l2_plane p;
- struct v4l2_buffer b;
+ unsigned int count;
+ unsigned int type;
+ unsigned int memory;
+ struct vb2_buffer *b;
struct vb2_fileio_buf bufs[VB2_MAX_FRAME];
unsigned int cur_index;
unsigned int initial_index;
@@ -975,6 +976,10 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
if (fileio == NULL)
return -ENOMEM;
+ fileio->b = kzalloc(q->buf_struct_size, GFP_KERNEL);
+ if (fileio->b == NULL)
+ return -ENOMEM;
+
fileio->read_once = q->fileio_read_once;
fileio->write_immediately = q->fileio_write_immediately;
@@ -982,11 +987,11 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
* Request buffers and use MMAP type to force driver
* to allocate buffers by itself.
*/
- fileio->req.count = count;
- fileio->req.memory = VB2_MEMORY_MMAP;
- fileio->req.type = q->type;
+ fileio->count = count;
+ fileio->memory = VB2_MEMORY_MMAP;
+ fileio->type = q->type;
q->fileio = fileio;
- ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+ ret = vb2_core_reqbufs(q, fileio->memory, &fileio->count);
if (ret)
goto err_kfree;
@@ -1015,24 +1020,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
* Read mode requires pre queuing of all buffers.
*/
if (read) {
- bool is_multiplanar = q->is_multiplanar;
-
/*
* Queue all buffers.
*/
for (i = 0; i < q->num_buffers; i++) {
- struct v4l2_buffer *b = &fileio->b;
+ struct vb2_buffer *b = fileio->b;
- memset(b, 0, sizeof(*b));
+ memset(b, 0, q->buf_struct_size);
b->type = q->type;
- if (is_multiplanar) {
- memset(&fileio->p, 0, sizeof(fileio->p));
- b->m.planes = &fileio->p;
- b->length = 1;
- }
b->memory = q->memory;
b->index = i;
- ret = vb2_internal_qbuf(q, b);
+ ret = vb2_core_qbuf(q, i, b);
if (ret)
goto err_reqbufs;
fileio->bufs[i].queued = 1;
@@ -1055,8 +1053,8 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
return ret;
err_reqbufs:
- fileio->req.count = 0;
- vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+ fileio->count = 0;
+ vb2_core_reqbufs(q, fileio->memory, &fileio->count);
err_kfree:
q->fileio = NULL;
@@ -1075,8 +1073,9 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q)
if (fileio) {
vb2_core_streamoff(q, q->type);
q->fileio = NULL;
- fileio->req.count = 0;
- vb2_reqbufs(q, &fileio->req);
+ fileio->count = 0;
+ vb2_core_reqbufs(q, fileio->memory, &fileio->count);
+ kfree(fileio->b);
kfree(fileio);
dprintk(3, "file io emulator closed\n");
}
@@ -1129,24 +1128,21 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
*/
index = fileio->cur_index;
if (index >= q->num_buffers) {
+ struct vb2_buffer *b = fileio->b;
+
/*
* Call vb2_dqbuf to get buffer back.
*/
- memset(&fileio->b, 0, sizeof(fileio->b));
- fileio->b.type = q->type;
- fileio->b.memory = q->memory;
- if (is_multiplanar) {
- memset(&fileio->p, 0, sizeof(fileio->p));
- fileio->b.m.planes = &fileio->p;
- fileio->b.length = 1;
- }
- ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
+ memset(b, 0, q->buf_struct_size);
+ b->type = q->type;
+ b->memory = q->memory;
+ ret = vb2_core_dqbuf(q, b, nonblock);
dprintk(5, "vb2_dqbuf result: %d\n", ret);
if (ret)
return ret;
fileio->dq_count += 1;
- fileio->cur_index = index = fileio->b.index;
+ fileio->cur_index = index = b->index;
buf = &fileio->bufs[index];
/*
@@ -1158,8 +1154,8 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
: vb2_plane_size(q->bufs[index], 0);
/* Compensate for data_offset on read in the multiplanar case. */
if (is_multiplanar && read &&
- fileio->b.m.planes[0].data_offset < buf->size) {
- buf->pos = fileio->b.m.planes[0].data_offset;
+ b->planes[0].data_offset < buf->size) {
+ buf->pos = b->planes[0].data_offset;
buf->size -= buf->pos;
}
} else {
@@ -1198,6 +1194,8 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
* Queue next buffer if required.
*/
if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
+ struct vb2_buffer *b = fileio->b;
+
/*
* Check if this is the last buffer to read.
*/
@@ -1209,20 +1207,15 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
/*
* Call vb2_qbuf and give buffer to the driver.
*/
- memset(&fileio->b, 0, sizeof(fileio->b));
- fileio->b.type = q->type;
- fileio->b.memory = q->memory;
- fileio->b.index = index;
- fileio->b.bytesused = buf->pos;
- if (is_multiplanar) {
- memset(&fileio->p, 0, sizeof(fileio->p));
- fileio->p.bytesused = buf->pos;
- fileio->b.m.planes = &fileio->p;
- fileio->b.length = 1;
- }
+ memset(b, 0, q->buf_struct_size);
+ b->type = q->type;
+ b->memory = q->memory;
+ b->index = index;
+ b->planes[0].bytesused = buf->pos;
+
if (set_timestamp)
- v4l2_get_timestamp(&fileio->b.timestamp);
- ret = vb2_internal_qbuf(q, &fileio->b);
+ b->timestamp = ktime_get_ns();
+ ret = vb2_core_qbuf(q, index, b);
dprintk(5, "vb2_dbuf result: %d\n", ret);
if (ret)
return ret;
@@ -1299,20 +1292,21 @@ static int vb2_thread(void *data)
for (;;) {
struct vb2_buffer *vb;
+ struct vb2_buffer *b = fileio->b;
/*
* Call vb2_dqbuf to get buffer back.
*/
- memset(&fileio->b, 0, sizeof(fileio->b));
- fileio->b.type = q->type;
- fileio->b.memory = q->memory;
+ memset(b, 0, q->buf_struct_size);
+ b->type = q->type;
+ b->memory = q->memory;
if (prequeue) {
- fileio->b.index = index++;
+ b->index = index++;
prequeue--;
} else {
call_void_qop(q, wait_finish, q);
if (!threadio->stop)
- ret = vb2_internal_dqbuf(q, &fileio->b, 0);
+ ret = vb2_core_dqbuf(q, b, 0);
call_void_qop(q, wait_prepare, q);
dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
}
@@ -1320,15 +1314,15 @@ static int vb2_thread(void *data)
break;
try_to_freeze();
- vb = q->bufs[fileio->b.index];
- if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
+ vb = q->bufs[b->index];
+ if (b->state == VB2_BUF_STATE_DONE)
if (threadio->fnc(vb, threadio->priv))
break;
call_void_qop(q, wait_finish, q);
if (set_timestamp)
- v4l2_get_timestamp(&fileio->b.timestamp);
+ b->timestamp = ktime_get_ns();
if (!threadio->stop)
- ret = vb2_internal_qbuf(q, &fileio->b);
+ ret = vb2_core_qbuf(q, b->index, b);
call_void_qop(q, wait_prepare, q);
if (ret || threadio->stop)
break;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 5/6] media: videobuf2: Refactor vb2_fileio_data and vb2_thread
2015-11-03 10:16 ` [RFC PATCH v9 5/6] media: videobuf2: Refactor vb2_fileio_data and vb2_thread Junghak Sung
@ 2015-11-05 11:10 ` Hans Verkuil
0 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2015-11-05 11:10 UTC (permalink / raw)
To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/03/15 11:16, Junghak Sung wrote:
> Replace v4l2-stuffs with common things in struct vb2_fileio_data and
> vb2_thread().
>
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Thanks!
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC PATCH v9 6/6] media: videobuf2: Move vb2_fileio_data and vb2_thread to core part
2015-11-03 10:16 [RFC PATCH v9] Refactoring Videobuf2 for common use Junghak Sung
` (4 preceding siblings ...)
2015-11-03 10:16 ` [RFC PATCH v9 5/6] media: videobuf2: Refactor vb2_fileio_data and vb2_thread Junghak Sung
@ 2015-11-03 10:16 ` Junghak Sung
2015-11-05 11:14 ` Hans Verkuil
5 siblings, 1 reply; 17+ messages in thread
From: Junghak Sung @ 2015-11-03 10:16 UTC (permalink / raw)
To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus,
pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
Junghak Sung
Move things related with vb2 file I/O and vb2_thread without doing any
functional changes. After that, videobuf2-internal.h is removed because
it is not necessary any more.
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
drivers/media/v4l2-core/videobuf2-core.c | 777 +++++++++++++++++++++++++-
drivers/media/v4l2-core/videobuf2-internal.h | 161 ------
drivers/media/v4l2-core/videobuf2-v4l2.c | 630 +--------------------
include/media/videobuf2-core.h | 43 ++
include/media/videobuf2-v4l2.h | 38 +-
5 files changed, 824 insertions(+), 825 deletions(-)
delete mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 33bdd81..f62c548 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -28,11 +28,155 @@
#include <trace/events/vb2.h>
-#include "videobuf2-internal.h"
+static int debug;
+module_param(debug, int, 0644);
-int vb2_debug;
-EXPORT_SYMBOL_GPL(vb2_debug);
-module_param_named(debug, vb2_debug, int, 0644);
+#define dprintk(level, fmt, arg...) \
+ do { \
+ if (debug >= level) \
+ pr_info("vb2-core: %s: " fmt, __func__, ## arg); \
+ } while (0)
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+
+/*
+ * If advanced debugging is on, then count how often each op is called
+ * successfully, which can either be per-buffer or per-queue.
+ *
+ * This makes it easy to check that the 'init' and 'cleanup'
+ * (and variations thereof) stay balanced.
+ */
+
+#define log_memop(vb, op) \
+ dprintk(2, "call_memop(%p, %d, %s)%s\n", \
+ (vb)->vb2_queue, (vb)->index, #op, \
+ (vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
+
+#define call_memop(vb, op, args...) \
+({ \
+ struct vb2_queue *_q = (vb)->vb2_queue; \
+ int err; \
+ \
+ log_memop(vb, op); \
+ err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0; \
+ if (!err) \
+ (vb)->cnt_mem_ ## op++; \
+ err; \
+})
+
+#define call_ptr_memop(vb, op, args...) \
+({ \
+ struct vb2_queue *_q = (vb)->vb2_queue; \
+ void *ptr; \
+ \
+ log_memop(vb, op); \
+ ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \
+ if (!IS_ERR_OR_NULL(ptr)) \
+ (vb)->cnt_mem_ ## op++; \
+ ptr; \
+})
+
+#define call_void_memop(vb, op, args...) \
+({ \
+ struct vb2_queue *_q = (vb)->vb2_queue; \
+ \
+ log_memop(vb, op); \
+ if (_q->mem_ops->op) \
+ _q->mem_ops->op(args); \
+ (vb)->cnt_mem_ ## op++; \
+})
+
+#define log_qop(q, op) \
+ dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \
+ (q)->ops->op ? "" : " (nop)")
+
+#define call_qop(q, op, args...) \
+({ \
+ int err; \
+ \
+ log_qop(q, op); \
+ err = (q)->ops->op ? (q)->ops->op(args) : 0; \
+ if (!err) \
+ (q)->cnt_ ## op++; \
+ err; \
+})
+
+#define call_void_qop(q, op, args...) \
+({ \
+ log_qop(q, op); \
+ if ((q)->ops->op) \
+ (q)->ops->op(args); \
+ (q)->cnt_ ## op++; \
+})
+
+#define log_vb_qop(vb, op, args...) \
+ dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \
+ (vb)->vb2_queue, (vb)->index, #op, \
+ (vb)->vb2_queue->ops->op ? "" : " (nop)")
+
+#define call_vb_qop(vb, op, args...) \
+({ \
+ int err; \
+ \
+ log_vb_qop(vb, op); \
+ err = (vb)->vb2_queue->ops->op ? \
+ (vb)->vb2_queue->ops->op(args) : 0; \
+ if (!err) \
+ (vb)->cnt_ ## op++; \
+ err; \
+})
+
+#define call_void_vb_qop(vb, op, args...) \
+({ \
+ log_vb_qop(vb, op); \
+ if ((vb)->vb2_queue->ops->op) \
+ (vb)->vb2_queue->ops->op(args); \
+ (vb)->cnt_ ## op++; \
+})
+
+#else
+
+#define call_memop(vb, op, args...) \
+ ((vb)->vb2_queue->mem_ops->op ? \
+ (vb)->vb2_queue->mem_ops->op(args) : 0)
+
+#define call_ptr_memop(vb, op, args...) \
+ ((vb)->vb2_queue->mem_ops->op ? \
+ (vb)->vb2_queue->mem_ops->op(args) : NULL)
+
+#define call_void_memop(vb, op, args...) \
+ do { \
+ if ((vb)->vb2_queue->mem_ops->op) \
+ (vb)->vb2_queue->mem_ops->op(args); \
+ } while (0)
+
+#define call_qop(q, op, args...) \
+ ((q)->ops->op ? (q)->ops->op(args) : 0)
+
+#define call_void_qop(q, op, args...) \
+ do { \
+ if ((q)->ops->op) \
+ (q)->ops->op(args); \
+ } while (0)
+
+#define call_vb_qop(vb, op, args...) \
+ ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
+
+#define call_void_vb_qop(vb, op, args...) \
+ do { \
+ if ((vb)->vb2_queue->ops->op) \
+ (vb)->vb2_queue->ops->op(args); \
+ } while (0)
+
+#endif
+
+#define call_bufop(q, op, args...) \
+({ \
+ int ret = 0; \
+ if (q && q->buf_ops && q->buf_ops->op) \
+ ret = q->buf_ops->op(args); \
+ ret; \
+})
static void __vb2_queue_cancel(struct vb2_queue *q);
static void __enqueue_in_driver(struct vb2_buffer *vb);
@@ -330,7 +474,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming ||
q->cnt_wait_prepare != q->cnt_wait_finish;
- if (unbalanced || vb2_debug) {
+ if (unbalanced || debug) {
pr_info("vb2: counters for queue %p:%s\n", q,
unbalanced ? " UNBALANCED!" : "");
pr_info("vb2: setup: %u start_streaming: %u stop_streaming: %u\n",
@@ -356,7 +500,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
vb->cnt_buf_prepare != vb->cnt_buf_finish ||
vb->cnt_buf_init != vb->cnt_buf_cleanup;
- if (unbalanced || vb2_debug) {
+ if (unbalanced || debug) {
pr_info("vb2: counters for queue %p, buffer %d:%s\n",
q, buffer, unbalanced ? " UNBALANCED!" : "");
pr_info("vb2: buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n",
@@ -2073,6 +2217,8 @@ int vb2_core_queue_init(struct vb2_queue *q)
}
EXPORT_SYMBOL_GPL(vb2_core_queue_init);
+static int __vb2_init_fileio(struct vb2_queue *q, int read);
+static int __vb2_cleanup_fileio(struct vb2_queue *q);
/**
* vb2_core_queue_release() - stop streaming, release the queue and free memory
* @q: videobuf2 queue
@@ -2083,6 +2229,7 @@ EXPORT_SYMBOL_GPL(vb2_core_queue_init);
*/
void vb2_core_queue_release(struct vb2_queue *q)
{
+ __vb2_cleanup_fileio(q);
__vb2_queue_cancel(q);
mutex_lock(&q->mmap_lock);
__vb2_queue_free(q, q->num_buffers);
@@ -2090,6 +2237,624 @@ void vb2_core_queue_release(struct vb2_queue *q)
}
EXPORT_SYMBOL_GPL(vb2_core_queue_release);
+/**
+ * vb2_core_poll() - implements poll userspace operation
+ * @q: videobuf2 queue
+ * @file: file argument passed to the poll file operation handler
+ * @wait: wait argument passed to the poll file operation handler
+ *
+ * This function implements poll file operation handler for a driver.
+ * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
+ * be informed that the file descriptor of a video device is available for
+ * reading.
+ * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
+ * will be reported as available for writing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from poll handler in driver.
+ */
+unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file,
+ poll_table *wait)
+{
+ unsigned long req_events = poll_requested_events(wait);
+ struct vb2_buffer *vb = NULL;
+ unsigned long flags;
+
+ if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
+ return 0;
+ if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
+ return 0;
+
+ /*
+ * Start file I/O emulator only if streaming API has not been used yet.
+ */
+ if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
+ if (!q->is_output && (q->io_modes & VB2_READ) &&
+ (req_events & (POLLIN | POLLRDNORM))) {
+ if (__vb2_init_fileio(q, 1))
+ return POLLERR;
+ }
+ if (q->is_output && (q->io_modes & VB2_WRITE) &&
+ (req_events & (POLLOUT | POLLWRNORM))) {
+ if (__vb2_init_fileio(q, 0))
+ return POLLERR;
+ /*
+ * Write to OUTPUT queue can be done immediately.
+ */
+ return POLLOUT | POLLWRNORM;
+ }
+ }
+
+ /*
+ * There is nothing to wait for if the queue isn't streaming, or if the
+ * error flag is set.
+ */
+ if (!vb2_is_streaming(q) || q->error)
+ return POLLERR;
+ /*
+ * For compatibility with vb1: if QBUF hasn't been called yet, then
+ * return POLLERR as well. This only affects capture queues, output
+ * queues will always initialize waiting_for_buffers to false.
+ */
+ if (q->waiting_for_buffers)
+ return POLLERR;
+
+ /*
+ * For output streams you can write as long as there are fewer buffers
+ * queued than there are buffers available.
+ */
+ if (q->is_output && q->queued_count < q->num_buffers)
+ return POLLOUT | POLLWRNORM;
+
+ if (list_empty(&q->done_list)) {
+ /*
+ * If the last buffer was dequeued from a capture queue,
+ * return immediately. DQBUF will return -EPIPE.
+ */
+ if (q->last_buffer_dequeued)
+ return POLLIN | POLLRDNORM;
+
+ poll_wait(file, &q->done_wq, wait);
+ }
+
+ /*
+ * Take first buffer available for dequeuing.
+ */
+ spin_lock_irqsave(&q->done_lock, flags);
+ if (!list_empty(&q->done_list))
+ vb = list_first_entry(&q->done_list, struct vb2_buffer,
+ done_entry);
+ spin_unlock_irqrestore(&q->done_lock, flags);
+
+ if (vb && (vb->state == VB2_BUF_STATE_DONE
+ || vb->state == VB2_BUF_STATE_ERROR)) {
+ return (q->is_output) ?
+ POLLOUT | POLLWRNORM :
+ POLLIN | POLLRDNORM;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_core_poll);
+
+/**
+ * struct vb2_fileio_buf - buffer context used by file io emulator
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. This structure is used for
+ * tracking context related to the buffers.
+ */
+struct vb2_fileio_buf {
+ void *vaddr;
+ unsigned int size;
+ unsigned int pos;
+ unsigned int queued:1;
+};
+
+/**
+ * struct vb2_fileio_data - queue context used by file io emulator
+ *
+ * @cur_index: the index of the buffer currently being read from or
+ * written to. If equal to q->num_buffers then a new buffer
+ * must be dequeued.
+ * @initial_index: in the read() case all buffers are queued up immediately
+ * in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
+ * buffers. However, in the write() case no buffers are initially
+ * queued, instead whenever a buffer is full it is queued up by
+ * __vb2_perform_fileio(). Only once all available buffers have
+ * been queued up will __vb2_perform_fileio() start to dequeue
+ * buffers. This means that initially __vb2_perform_fileio()
+ * needs to know what buffer index to use when it is queuing up
+ * the buffers for the first time. That initial index is stored
+ * in this field. Once it is equal to q->num_buffers all
+ * available buffers have been queued and __vb2_perform_fileio()
+ * should start the normal dequeue/queue cycle.
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. For proper operation it required
+ * this structure to save the driver state between each call of the read
+ * or write function.
+ */
+struct vb2_fileio_data {
+ unsigned int count;
+ unsigned int type;
+ unsigned int memory;
+ struct vb2_buffer *b;
+ struct vb2_fileio_buf bufs[VB2_MAX_FRAME];
+ unsigned int cur_index;
+ unsigned int initial_index;
+ unsigned int q_count;
+ unsigned int dq_count;
+ unsigned read_once:1;
+ unsigned write_immediately:1;
+};
+
+/**
+ * __vb2_init_fileio() - initialize file io emulator
+ * @q: videobuf2 queue
+ * @read: mode selector (1 means read, 0 means write)
+ */
+static int __vb2_init_fileio(struct vb2_queue *q, int read)
+{
+ struct vb2_fileio_data *fileio;
+ int i, ret;
+ unsigned int count = 0;
+
+ /*
+ * Sanity check
+ */
+ if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
+ (!read && !(q->io_modes & VB2_WRITE))))
+ return -EINVAL;
+
+ /*
+ * Check if device supports mapping buffers to kernel virtual space.
+ */
+ if (!q->mem_ops->vaddr)
+ return -EBUSY;
+
+ /*
+ * Check if streaming api has not been already activated.
+ */
+ if (q->streaming || q->num_buffers > 0)
+ return -EBUSY;
+
+ /*
+ * Start with count 1, driver can increase it in queue_setup()
+ */
+ count = 1;
+
+ dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
+ (read) ? "read" : "write", count, q->fileio_read_once,
+ q->fileio_write_immediately);
+
+ fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
+ if (fileio == NULL)
+ return -ENOMEM;
+
+ fileio->b = kzalloc(q->buf_struct_size, GFP_KERNEL);
+ if (fileio->b == NULL)
+ return -ENOMEM;
+
+ fileio->read_once = q->fileio_read_once;
+ fileio->write_immediately = q->fileio_write_immediately;
+
+ /*
+ * Request buffers and use MMAP type to force driver
+ * to allocate buffers by itself.
+ */
+ fileio->count = count;
+ fileio->memory = VB2_MEMORY_MMAP;
+ fileio->type = q->type;
+ q->fileio = fileio;
+ ret = vb2_core_reqbufs(q, fileio->memory, &fileio->count);
+ if (ret)
+ goto err_kfree;
+
+ /*
+ * Check if plane_count is correct
+ * (multiplane buffers are not supported).
+ */
+ if (q->bufs[0]->num_planes != 1) {
+ ret = -EBUSY;
+ goto err_reqbufs;
+ }
+
+ /*
+ * Get kernel address of each buffer.
+ */
+ for (i = 0; i < q->num_buffers; i++) {
+ fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+ if (fileio->bufs[i].vaddr == NULL) {
+ ret = -EINVAL;
+ goto err_reqbufs;
+ }
+ fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+ }
+
+ /*
+ * Read mode requires pre queuing of all buffers.
+ */
+ if (read) {
+ /*
+ * Queue all buffers.
+ */
+ for (i = 0; i < q->num_buffers; i++) {
+ struct vb2_buffer *b = fileio->b;
+
+ memset(b, 0, q->buf_struct_size);
+ b->type = q->type;
+ b->memory = q->memory;
+ b->index = i;
+ ret = vb2_core_qbuf(q, i, b);
+ if (ret)
+ goto err_reqbufs;
+ fileio->bufs[i].queued = 1;
+ }
+ /*
+ * All buffers have been queued, so mark that by setting
+ * initial_index to q->num_buffers
+ */
+ fileio->initial_index = q->num_buffers;
+ fileio->cur_index = q->num_buffers;
+ }
+
+ /*
+ * Start streaming.
+ */
+ ret = vb2_core_streamon(q, q->type);
+ if (ret)
+ goto err_reqbufs;
+
+ return ret;
+
+err_reqbufs:
+ fileio->count = 0;
+ vb2_core_reqbufs(q, fileio->memory, &fileio->count);
+
+err_kfree:
+ q->fileio = NULL;
+ kfree(fileio);
+ return ret;
+}
+
+/**
+ * __vb2_cleanup_fileio() - free resourced used by file io emulator
+ * @q: videobuf2 queue
+ */
+static int __vb2_cleanup_fileio(struct vb2_queue *q)
+{
+ struct vb2_fileio_data *fileio = q->fileio;
+
+ if (fileio) {
+ vb2_core_streamoff(q, q->type);
+ q->fileio = NULL;
+ fileio->count = 0;
+ vb2_core_reqbufs(q, fileio->memory, &fileio->count);
+ kfree(fileio->b);
+ kfree(fileio);
+ dprintk(3, "file io emulator closed\n");
+ }
+ return 0;
+}
+
+/**
+ * __vb2_perform_fileio() - perform a single file io (read or write) operation
+ * @q: videobuf2 queue
+ * @data: pointed to target userspace buffer
+ * @count: number of bytes to read or write
+ * @ppos: file handle position tracking pointer
+ * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking)
+ * @read: access mode selector (1 means read, 0 means write)
+ */
+static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblock, int read)
+{
+ struct vb2_fileio_data *fileio;
+ struct vb2_fileio_buf *buf;
+ bool is_multiplanar = q->is_multiplanar;
+ /*
+ * When using write() to write data to an output video node the vb2 core
+ * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
+ * else is able to provide this information with the write() operation.
+ */
+ bool set_timestamp = !read && q->set_timestamp;
+ int ret, index;
+
+ dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
+ read ? "read" : "write", (long)*ppos, count,
+ nonblock ? "non" : "");
+
+ if (!data)
+ return -EINVAL;
+
+ /*
+ * Initialize emulator on first call.
+ */
+ if (!vb2_fileio_is_active(q)) {
+ ret = __vb2_init_fileio(q, read);
+ dprintk(3, "vb2_init_fileio result: %d\n", ret);
+ if (ret)
+ return ret;
+ }
+ fileio = q->fileio;
+
+ /*
+ * Check if we need to dequeue the buffer.
+ */
+ index = fileio->cur_index;
+ if (index >= q->num_buffers) {
+ struct vb2_buffer *b = fileio->b;
+
+ /*
+ * Call vb2_dqbuf to get buffer back.
+ */
+ memset(b, 0, q->buf_struct_size);
+ b->type = q->type;
+ b->memory = q->memory;
+ ret = vb2_core_dqbuf(q, b, nonblock);
+ dprintk(5, "vb2_dqbuf result: %d\n", ret);
+ if (ret)
+ return ret;
+ fileio->dq_count += 1;
+
+ fileio->cur_index = index = b->index;
+ buf = &fileio->bufs[index];
+
+ /*
+ * Get number of bytes filled by the driver
+ */
+ buf->pos = 0;
+ buf->queued = 0;
+ buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
+ : vb2_plane_size(q->bufs[index], 0);
+ /* Compensate for data_offset on read in the multiplanar case. */
+ if (is_multiplanar && read &&
+ b->planes[0].data_offset < buf->size) {
+ buf->pos = b->planes[0].data_offset;
+ buf->size -= buf->pos;
+ }
+ } else {
+ buf = &fileio->bufs[index];
+ }
+
+ /*
+ * Limit count on last few bytes of the buffer.
+ */
+ if (buf->pos + count > buf->size) {
+ count = buf->size - buf->pos;
+ dprintk(5, "reducing read count: %zd\n", count);
+ }
+
+ /*
+ * Transfer data to userspace.
+ */
+ dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
+ count, index, buf->pos);
+ if (read)
+ ret = copy_to_user(data, buf->vaddr + buf->pos, count);
+ else
+ ret = copy_from_user(buf->vaddr + buf->pos, data, count);
+ if (ret) {
+ dprintk(3, "error copying data\n");
+ return -EFAULT;
+ }
+
+ /*
+ * Update counters.
+ */
+ buf->pos += count;
+ *ppos += count;
+
+ /*
+ * Queue next buffer if required.
+ */
+ if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
+ struct vb2_buffer *b = fileio->b;
+
+ /*
+ * Check if this is the last buffer to read.
+ */
+ if (read && fileio->read_once && fileio->dq_count == 1) {
+ dprintk(3, "read limit reached\n");
+ return __vb2_cleanup_fileio(q);
+ }
+
+ /*
+ * Call vb2_qbuf and give buffer to the driver.
+ */
+ memset(b, 0, q->buf_struct_size);
+ b->type = q->type;
+ b->memory = q->memory;
+ b->index = index;
+ b->planes[0].bytesused = buf->pos;
+
+ if (set_timestamp)
+ b->timestamp = ktime_get_ns();
+ ret = vb2_core_qbuf(q, index, b);
+ dprintk(5, "vb2_dbuf result: %d\n", ret);
+ if (ret)
+ return ret;
+
+ /*
+ * Buffer has been queued, update the status
+ */
+ buf->pos = 0;
+ buf->queued = 1;
+ buf->size = vb2_plane_size(q->bufs[index], 0);
+ fileio->q_count += 1;
+ /*
+ * If we are queuing up buffers for the first time, then
+ * increase initial_index by one.
+ */
+ if (fileio->initial_index < q->num_buffers)
+ fileio->initial_index++;
+ /*
+ * The next buffer to use is either a buffer that's going to be
+ * queued for the first time (initial_index < q->num_buffers)
+ * or it is equal to q->num_buffers, meaning that the next
+ * time we need to dequeue a buffer since we've now queued up
+ * all the 'first time' buffers.
+ */
+ fileio->cur_index = fileio->initial_index;
+ }
+
+ /*
+ * Return proper number of bytes processed.
+ */
+ if (ret == 0)
+ ret = count;
+ return ret;
+}
+
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblocking)
+{
+ return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
+}
+EXPORT_SYMBOL_GPL(vb2_read);
+
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+ loff_t *ppos, int nonblocking)
+{
+ return __vb2_perform_fileio(q, (char __user *) data, count,
+ ppos, nonblocking, 0);
+}
+EXPORT_SYMBOL_GPL(vb2_write);
+
+struct vb2_threadio_data {
+ struct task_struct *thread;
+ vb2_thread_fnc fnc;
+ void *priv;
+ bool stop;
+};
+
+static int vb2_thread(void *data)
+{
+ struct vb2_queue *q = data;
+ struct vb2_threadio_data *threadio = q->threadio;
+ struct vb2_fileio_data *fileio = q->fileio;
+ bool set_timestamp = false;
+ int prequeue = 0;
+ int index = 0;
+ int ret = 0;
+
+ if (q->is_output) {
+ prequeue = q->num_buffers;
+ set_timestamp = q->set_timestamp;
+ }
+
+ set_freezable();
+
+ for (;;) {
+ struct vb2_buffer *vb;
+ struct vb2_buffer *b = fileio->b;
+
+ /*
+ * Call vb2_dqbuf to get buffer back.
+ */
+ memset(b, 0, q->buf_struct_size);
+ b->type = q->type;
+ b->memory = q->memory;
+ if (prequeue) {
+ b->index = index++;
+ prequeue--;
+ } else {
+ call_void_qop(q, wait_finish, q);
+ if (!threadio->stop)
+ ret = vb2_core_dqbuf(q, b, 0);
+ call_void_qop(q, wait_prepare, q);
+ dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
+ }
+ if (ret || threadio->stop)
+ break;
+ try_to_freeze();
+
+ vb = q->bufs[b->index];
+ if (b->state == VB2_BUF_STATE_DONE)
+ if (threadio->fnc(vb, threadio->priv))
+ break;
+ call_void_qop(q, wait_finish, q);
+ if (set_timestamp)
+ b->timestamp = ktime_get_ns();;
+ if (!threadio->stop)
+ ret = vb2_core_qbuf(q, b->index, b);
+ call_void_qop(q, wait_prepare, q);
+ if (ret || threadio->stop)
+ break;
+ }
+
+ /* Hmm, linux becomes *very* unhappy without this ... */
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ }
+ return 0;
+}
+
+/*
+ * This function should not be used for anything else but the videobuf2-dvb
+ * support. If you think you have another good use-case for this, then please
+ * contact the linux-media mailinglist first.
+ */
+int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
+ const char *thread_name)
+{
+ struct vb2_threadio_data *threadio;
+ int ret = 0;
+
+ if (q->threadio)
+ return -EBUSY;
+ if (vb2_is_busy(q))
+ return -EBUSY;
+ if (WARN_ON(q->fileio))
+ return -EBUSY;
+
+ threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
+ if (threadio == NULL)
+ return -ENOMEM;
+ threadio->fnc = fnc;
+ threadio->priv = priv;
+
+ ret = __vb2_init_fileio(q, !q->is_output);
+ dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
+ if (ret)
+ goto nomem;
+ q->threadio = threadio;
+ threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
+ if (IS_ERR(threadio->thread)) {
+ ret = PTR_ERR(threadio->thread);
+ threadio->thread = NULL;
+ goto nothread;
+ }
+ return 0;
+
+nothread:
+ __vb2_cleanup_fileio(q);
+nomem:
+ kfree(threadio);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_start);
+
+int vb2_thread_stop(struct vb2_queue *q)
+{
+ struct vb2_threadio_data *threadio = q->threadio;
+ int err;
+
+ if (threadio == NULL)
+ return 0;
+ threadio->stop = true;
+ /* Wake up all pending sleeps in the thread */
+ vb2_queue_error(q);
+ err = kthread_stop(threadio->thread);
+ __vb2_cleanup_fileio(q);
+ threadio->thread = NULL;
+ kfree(threadio);
+ q->threadio = NULL;
+ return err;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_stop);
+
MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
deleted file mode 100644
index 79018c7..0000000
--- a/drivers/media/v4l2-core/videobuf2-internal.h
+++ /dev/null
@@ -1,161 +0,0 @@
-#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
-#define _MEDIA_VIDEOBUF2_INTERNAL_H
-
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <media/videobuf2-core.h>
-
-extern int vb2_debug;
-
-#define dprintk(level, fmt, arg...) \
- do { \
- if (vb2_debug >= level) \
- pr_info("vb2: %s: " fmt, __func__, ## arg); \
- } while (0)
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-
-/*
- * If advanced debugging is on, then count how often each op is called
- * successfully, which can either be per-buffer or per-queue.
- *
- * This makes it easy to check that the 'init' and 'cleanup'
- * (and variations thereof) stay balanced.
- */
-
-#define log_memop(vb, op) \
- dprintk(2, "call_memop(%p, %d, %s)%s\n", \
- (vb)->vb2_queue, (vb)->index, #op, \
- (vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
-
-#define call_memop(vb, op, args...) \
-({ \
- struct vb2_queue *_q = (vb)->vb2_queue; \
- int err; \
- \
- log_memop(vb, op); \
- err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0; \
- if (!err) \
- (vb)->cnt_mem_ ## op++; \
- err; \
-})
-
-#define call_ptr_memop(vb, op, args...) \
-({ \
- struct vb2_queue *_q = (vb)->vb2_queue; \
- void *ptr; \
- \
- log_memop(vb, op); \
- ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \
- if (!IS_ERR_OR_NULL(ptr)) \
- (vb)->cnt_mem_ ## op++; \
- ptr; \
-})
-
-#define call_void_memop(vb, op, args...) \
-({ \
- struct vb2_queue *_q = (vb)->vb2_queue; \
- \
- log_memop(vb, op); \
- if (_q->mem_ops->op) \
- _q->mem_ops->op(args); \
- (vb)->cnt_mem_ ## op++; \
-})
-
-#define log_qop(q, op) \
- dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \
- (q)->ops->op ? "" : " (nop)")
-
-#define call_qop(q, op, args...) \
-({ \
- int err; \
- \
- log_qop(q, op); \
- err = (q)->ops->op ? (q)->ops->op(args) : 0; \
- if (!err) \
- (q)->cnt_ ## op++; \
- err; \
-})
-
-#define call_void_qop(q, op, args...) \
-({ \
- log_qop(q, op); \
- if ((q)->ops->op) \
- (q)->ops->op(args); \
- (q)->cnt_ ## op++; \
-})
-
-#define log_vb_qop(vb, op, args...) \
- dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \
- (vb)->vb2_queue, (vb)->index, #op, \
- (vb)->vb2_queue->ops->op ? "" : " (nop)")
-
-#define call_vb_qop(vb, op, args...) \
-({ \
- int err; \
- \
- log_vb_qop(vb, op); \
- err = (vb)->vb2_queue->ops->op ? \
- (vb)->vb2_queue->ops->op(args) : 0; \
- if (!err) \
- (vb)->cnt_ ## op++; \
- err; \
-})
-
-#define call_void_vb_qop(vb, op, args...) \
-({ \
- log_vb_qop(vb, op); \
- if ((vb)->vb2_queue->ops->op) \
- (vb)->vb2_queue->ops->op(args); \
- (vb)->cnt_ ## op++; \
-})
-
-#else
-
-#define call_memop(vb, op, args...) \
- ((vb)->vb2_queue->mem_ops->op ? \
- (vb)->vb2_queue->mem_ops->op(args) : 0)
-
-#define call_ptr_memop(vb, op, args...) \
- ((vb)->vb2_queue->mem_ops->op ? \
- (vb)->vb2_queue->mem_ops->op(args) : NULL)
-
-#define call_void_memop(vb, op, args...) \
- do { \
- if ((vb)->vb2_queue->mem_ops->op) \
- (vb)->vb2_queue->mem_ops->op(args); \
- } while (0)
-
-#define call_qop(q, op, args...) \
- ((q)->ops->op ? (q)->ops->op(args) : 0)
-
-#define call_void_qop(q, op, args...) \
- do { \
- if ((q)->ops->op) \
- (q)->ops->op(args); \
- } while (0)
-
-#define call_vb_qop(vb, op, args...) \
- ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
-
-#define call_void_vb_qop(vb, op, args...) \
- do { \
- if ((vb)->vb2_queue->ops->op) \
- (vb)->vb2_queue->ops->op(args); \
- } while (0)
-
-#endif
-
-#define call_bufop(q, op, args...) \
-({ \
- int ret = 0; \
- if (q && q->buf_ops && q->buf_ops->op) \
- ret = q->buf_ops->op(args); \
- ret; \
-})
-
-bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
-int vb2_verify_memory_type(struct vb2_queue *q,
- enum vb2_memory memory, unsigned int type);
-#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index f806ef4..2d382ad 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -31,7 +31,14 @@
#include <media/videobuf2-v4l2.h>
-#include "videobuf2-internal.h"
+static int debug;
+module_param(debug, int, 0644);
+
+#define dprintk(level, fmt, arg...) \
+ do { \
+ if (debug >= level) \
+ pr_info("vb2-v4l2: %s: " fmt, __func__, ## arg); \
+ } while (0)
/* Flags that are set by the vb2 core */
#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
@@ -727,9 +734,6 @@ int vb2_queue_init(struct vb2_queue *q)
}
EXPORT_SYMBOL_GPL(vb2_queue_init);
-static int __vb2_init_fileio(struct vb2_queue *q, int read);
-static int __vb2_cleanup_fileio(struct vb2_queue *q);
-
/**
* vb2_queue_release() - stop streaming, release the queue and free memory
* @q: videobuf2 queue
@@ -740,110 +744,11 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q);
*/
void vb2_queue_release(struct vb2_queue *q)
{
- __vb2_cleanup_fileio(q);
vb2_core_queue_release(q);
}
EXPORT_SYMBOL_GPL(vb2_queue_release);
/**
- * vb2_core_poll() - implements poll userspace operation
- * @q: videobuf2 queue
- * @file: file argument passed to the poll file operation handler
- * @wait: wait argument passed to the poll file operation handler
- *
- * This function implements poll file operation handler for a driver.
- * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
- * be informed that the file descriptor of a video device is available for
- * reading.
- * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
- * will be reported as available for writing.
- *
- * The return values from this function are intended to be directly returned
- * from poll handler in driver.
- */
-unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file,
- poll_table *wait)
-{
- unsigned long req_events = poll_requested_events(wait);
- struct vb2_buffer *vb = NULL;
- unsigned long flags;
-
- if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
- return 0;
- if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
- return 0;
-
- /*
- * Start file I/O emulator only if streaming API has not been used yet.
- */
- if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
- if (!q->is_output && (q->io_modes & VB2_READ) &&
- (req_events & (POLLIN | POLLRDNORM))) {
- if (__vb2_init_fileio(q, 1))
- return POLLERR;
- }
- if (q->is_output && (q->io_modes & VB2_WRITE) &&
- (req_events & (POLLOUT | POLLWRNORM))) {
- if (__vb2_init_fileio(q, 0))
- return POLLERR;
- /*
- * Write to OUTPUT queue can be done immediately.
- */
- return POLLOUT | POLLWRNORM;
- }
- }
-
- /*
- * There is nothing to wait for if the queue isn't streaming, or if the
- * error flag is set.
- */
- if (!vb2_is_streaming(q) || q->error)
- return POLLERR;
- /*
- * For compatibility with vb1: if QBUF hasn't been called yet, then
- * return POLLERR as well. This only affects capture queues, output
- * queues will always initialize waiting_for_buffers to false.
- */
- if (q->waiting_for_buffers)
- return POLLERR;
-
- /*
- * For output streams you can write as long as there are fewer buffers
- * queued than there are buffers available.
- */
- if (q->is_output && q->queued_count < q->num_buffers)
- return POLLOUT | POLLWRNORM;
-
- if (list_empty(&q->done_list)) {
- /*
- * If the last buffer was dequeued from a capture queue,
- * return immediately. DQBUF will return -EPIPE.
- */
- if (q->last_buffer_dequeued)
- return POLLIN | POLLRDNORM;
-
- poll_wait(file, &q->done_wq, wait);
- }
-
- /*
- * Take first buffer available for dequeuing.
- */
- spin_lock_irqsave(&q->done_lock, flags);
- if (!list_empty(&q->done_list))
- vb = list_first_entry(&q->done_list, struct vb2_buffer,
- done_entry);
- spin_unlock_irqrestore(&q->done_lock, flags);
-
- if (vb && (vb->state == VB2_BUF_STATE_DONE
- || vb->state == VB2_BUF_STATE_ERROR)) {
- return (q->is_output) ?
- POLLOUT | POLLWRNORM :
- POLLIN | POLLRDNORM;
- }
- return 0;
-}
-
-/**
* vb2_poll() - implements poll userspace operation
* @q: videobuf2 queue
* @file: file argument passed to the poll file operation handler
@@ -881,525 +786,6 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
}
EXPORT_SYMBOL_GPL(vb2_poll);
-/**
- * struct vb2_fileio_buf - buffer context used by file io emulator
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. This structure is used for
- * tracking context related to the buffers.
- */
-struct vb2_fileio_buf {
- void *vaddr;
- unsigned int size;
- unsigned int pos;
- unsigned int queued:1;
-};
-
-/**
- * struct vb2_fileio_data - queue context used by file io emulator
- *
- * @cur_index: the index of the buffer currently being read from or
- * written to. If equal to q->num_buffers then a new buffer
- * must be dequeued.
- * @initial_index: in the read() case all buffers are queued up immediately
- * in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
- * buffers. However, in the write() case no buffers are initially
- * queued, instead whenever a buffer is full it is queued up by
- * __vb2_perform_fileio(). Only once all available buffers have
- * been queued up will __vb2_perform_fileio() start to dequeue
- * buffers. This means that initially __vb2_perform_fileio()
- * needs to know what buffer index to use when it is queuing up
- * the buffers for the first time. That initial index is stored
- * in this field. Once it is equal to q->num_buffers all
- * available buffers have been queued and __vb2_perform_fileio()
- * should start the normal dequeue/queue cycle.
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. For proper operation it required
- * this structure to save the driver state between each call of the read
- * or write function.
- */
-struct vb2_fileio_data {
- unsigned int count;
- unsigned int type;
- unsigned int memory;
- struct vb2_buffer *b;
- struct vb2_fileio_buf bufs[VB2_MAX_FRAME];
- unsigned int cur_index;
- unsigned int initial_index;
- unsigned int q_count;
- unsigned int dq_count;
- unsigned read_once:1;
- unsigned write_immediately:1;
-};
-
-/**
- * __vb2_init_fileio() - initialize file io emulator
- * @q: videobuf2 queue
- * @read: mode selector (1 means read, 0 means write)
- */
-static int __vb2_init_fileio(struct vb2_queue *q, int read)
-{
- struct vb2_fileio_data *fileio;
- int i, ret;
- unsigned int count = 0;
-
- /*
- * Sanity check
- */
- if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
- (!read && !(q->io_modes & VB2_WRITE))))
- return -EINVAL;
-
- /*
- * Check if device supports mapping buffers to kernel virtual space.
- */
- if (!q->mem_ops->vaddr)
- return -EBUSY;
-
- /*
- * Check if streaming api has not been already activated.
- */
- if (q->streaming || q->num_buffers > 0)
- return -EBUSY;
-
- /*
- * Start with count 1, driver can increase it in queue_setup()
- */
- count = 1;
-
- dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
- (read) ? "read" : "write", count, q->fileio_read_once,
- q->fileio_write_immediately);
-
- fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
- if (fileio == NULL)
- return -ENOMEM;
-
- fileio->b = kzalloc(q->buf_struct_size, GFP_KERNEL);
- if (fileio->b == NULL)
- return -ENOMEM;
-
- fileio->read_once = q->fileio_read_once;
- fileio->write_immediately = q->fileio_write_immediately;
-
- /*
- * Request buffers and use MMAP type to force driver
- * to allocate buffers by itself.
- */
- fileio->count = count;
- fileio->memory = VB2_MEMORY_MMAP;
- fileio->type = q->type;
- q->fileio = fileio;
- ret = vb2_core_reqbufs(q, fileio->memory, &fileio->count);
- if (ret)
- goto err_kfree;
-
- /*
- * Check if plane_count is correct
- * (multiplane buffers are not supported).
- */
- if (q->bufs[0]->num_planes != 1) {
- ret = -EBUSY;
- goto err_reqbufs;
- }
-
- /*
- * Get kernel address of each buffer.
- */
- for (i = 0; i < q->num_buffers; i++) {
- fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
- if (fileio->bufs[i].vaddr == NULL) {
- ret = -EINVAL;
- goto err_reqbufs;
- }
- fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
- }
-
- /*
- * Read mode requires pre queuing of all buffers.
- */
- if (read) {
- /*
- * Queue all buffers.
- */
- for (i = 0; i < q->num_buffers; i++) {
- struct vb2_buffer *b = fileio->b;
-
- memset(b, 0, q->buf_struct_size);
- b->type = q->type;
- b->memory = q->memory;
- b->index = i;
- ret = vb2_core_qbuf(q, i, b);
- if (ret)
- goto err_reqbufs;
- fileio->bufs[i].queued = 1;
- }
- /*
- * All buffers have been queued, so mark that by setting
- * initial_index to q->num_buffers
- */
- fileio->initial_index = q->num_buffers;
- fileio->cur_index = q->num_buffers;
- }
-
- /*
- * Start streaming.
- */
- ret = vb2_core_streamon(q, q->type);
- if (ret)
- goto err_reqbufs;
-
- return ret;
-
-err_reqbufs:
- fileio->count = 0;
- vb2_core_reqbufs(q, fileio->memory, &fileio->count);
-
-err_kfree:
- q->fileio = NULL;
- kfree(fileio);
- return ret;
-}
-
-/**
- * __vb2_cleanup_fileio() - free resourced used by file io emulator
- * @q: videobuf2 queue
- */
-static int __vb2_cleanup_fileio(struct vb2_queue *q)
-{
- struct vb2_fileio_data *fileio = q->fileio;
-
- if (fileio) {
- vb2_core_streamoff(q, q->type);
- q->fileio = NULL;
- fileio->count = 0;
- vb2_core_reqbufs(q, fileio->memory, &fileio->count);
- kfree(fileio->b);
- kfree(fileio);
- dprintk(3, "file io emulator closed\n");
- }
- return 0;
-}
-
-/**
- * __vb2_perform_fileio() - perform a single file io (read or write) operation
- * @q: videobuf2 queue
- * @data: pointed to target userspace buffer
- * @count: number of bytes to read or write
- * @ppos: file handle position tracking pointer
- * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking)
- * @read: access mode selector (1 means read, 0 means write)
- */
-static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblock, int read)
-{
- struct vb2_fileio_data *fileio;
- struct vb2_fileio_buf *buf;
- bool is_multiplanar = q->is_multiplanar;
- /*
- * When using write() to write data to an output video node the vb2 core
- * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
- * else is able to provide this information with the write() operation.
- */
- bool set_timestamp = !read && q->set_timestamp;
- int ret, index;
-
- dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
- read ? "read" : "write", (long)*ppos, count,
- nonblock ? "non" : "");
-
- if (!data)
- return -EINVAL;
-
- /*
- * Initialize emulator on first call.
- */
- if (!vb2_fileio_is_active(q)) {
- ret = __vb2_init_fileio(q, read);
- dprintk(3, "vb2_init_fileio result: %d\n", ret);
- if (ret)
- return ret;
- }
- fileio = q->fileio;
-
- /*
- * Check if we need to dequeue the buffer.
- */
- index = fileio->cur_index;
- if (index >= q->num_buffers) {
- struct vb2_buffer *b = fileio->b;
-
- /*
- * Call vb2_dqbuf to get buffer back.
- */
- memset(b, 0, q->buf_struct_size);
- b->type = q->type;
- b->memory = q->memory;
- ret = vb2_core_dqbuf(q, b, nonblock);
- dprintk(5, "vb2_dqbuf result: %d\n", ret);
- if (ret)
- return ret;
- fileio->dq_count += 1;
-
- fileio->cur_index = index = b->index;
- buf = &fileio->bufs[index];
-
- /*
- * Get number of bytes filled by the driver
- */
- buf->pos = 0;
- buf->queued = 0;
- buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
- : vb2_plane_size(q->bufs[index], 0);
- /* Compensate for data_offset on read in the multiplanar case. */
- if (is_multiplanar && read &&
- b->planes[0].data_offset < buf->size) {
- buf->pos = b->planes[0].data_offset;
- buf->size -= buf->pos;
- }
- } else {
- buf = &fileio->bufs[index];
- }
-
- /*
- * Limit count on last few bytes of the buffer.
- */
- if (buf->pos + count > buf->size) {
- count = buf->size - buf->pos;
- dprintk(5, "reducing read count: %zd\n", count);
- }
-
- /*
- * Transfer data to userspace.
- */
- dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
- count, index, buf->pos);
- if (read)
- ret = copy_to_user(data, buf->vaddr + buf->pos, count);
- else
- ret = copy_from_user(buf->vaddr + buf->pos, data, count);
- if (ret) {
- dprintk(3, "error copying data\n");
- return -EFAULT;
- }
-
- /*
- * Update counters.
- */
- buf->pos += count;
- *ppos += count;
-
- /*
- * Queue next buffer if required.
- */
- if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
- struct vb2_buffer *b = fileio->b;
-
- /*
- * Check if this is the last buffer to read.
- */
- if (read && fileio->read_once && fileio->dq_count == 1) {
- dprintk(3, "read limit reached\n");
- return __vb2_cleanup_fileio(q);
- }
-
- /*
- * Call vb2_qbuf and give buffer to the driver.
- */
- memset(b, 0, q->buf_struct_size);
- b->type = q->type;
- b->memory = q->memory;
- b->index = index;
- b->planes[0].bytesused = buf->pos;
-
- if (set_timestamp)
- b->timestamp = ktime_get_ns();
- ret = vb2_core_qbuf(q, index, b);
- dprintk(5, "vb2_dbuf result: %d\n", ret);
- if (ret)
- return ret;
-
- /*
- * Buffer has been queued, update the status
- */
- buf->pos = 0;
- buf->queued = 1;
- buf->size = vb2_plane_size(q->bufs[index], 0);
- fileio->q_count += 1;
- /*
- * If we are queuing up buffers for the first time, then
- * increase initial_index by one.
- */
- if (fileio->initial_index < q->num_buffers)
- fileio->initial_index++;
- /*
- * The next buffer to use is either a buffer that's going to be
- * queued for the first time (initial_index < q->num_buffers)
- * or it is equal to q->num_buffers, meaning that the next
- * time we need to dequeue a buffer since we've now queued up
- * all the 'first time' buffers.
- */
- fileio->cur_index = fileio->initial_index;
- }
-
- /*
- * Return proper number of bytes processed.
- */
- if (ret == 0)
- ret = count;
- return ret;
-}
-
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblocking)
-{
- return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
-}
-EXPORT_SYMBOL_GPL(vb2_read);
-
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
- loff_t *ppos, int nonblocking)
-{
- return __vb2_perform_fileio(q, (char __user *) data, count,
- ppos, nonblocking, 0);
-}
-EXPORT_SYMBOL_GPL(vb2_write);
-
-struct vb2_threadio_data {
- struct task_struct *thread;
- vb2_thread_fnc fnc;
- void *priv;
- bool stop;
-};
-
-static int vb2_thread(void *data)
-{
- struct vb2_queue *q = data;
- struct vb2_threadio_data *threadio = q->threadio;
- struct vb2_fileio_data *fileio = q->fileio;
- bool set_timestamp = false;
- int prequeue = 0;
- int index = 0;
- int ret = 0;
-
- if (q->is_output) {
- prequeue = q->num_buffers;
- set_timestamp = q->set_timestamp;
- }
-
- set_freezable();
-
- for (;;) {
- struct vb2_buffer *vb;
- struct vb2_buffer *b = fileio->b;
-
- /*
- * Call vb2_dqbuf to get buffer back.
- */
- memset(b, 0, q->buf_struct_size);
- b->type = q->type;
- b->memory = q->memory;
- if (prequeue) {
- b->index = index++;
- prequeue--;
- } else {
- call_void_qop(q, wait_finish, q);
- if (!threadio->stop)
- ret = vb2_core_dqbuf(q, b, 0);
- call_void_qop(q, wait_prepare, q);
- dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
- }
- if (ret || threadio->stop)
- break;
- try_to_freeze();
-
- vb = q->bufs[b->index];
- if (b->state == VB2_BUF_STATE_DONE)
- if (threadio->fnc(vb, threadio->priv))
- break;
- call_void_qop(q, wait_finish, q);
- if (set_timestamp)
- b->timestamp = ktime_get_ns();
- if (!threadio->stop)
- ret = vb2_core_qbuf(q, b->index, b);
- call_void_qop(q, wait_prepare, q);
- if (ret || threadio->stop)
- break;
- }
-
- /* Hmm, linux becomes *very* unhappy without this ... */
- while (!kthread_should_stop()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- }
- return 0;
-}
-
-/*
- * This function should not be used for anything else but the videobuf2-dvb
- * support. If you think you have another good use-case for this, then please
- * contact the linux-media mailinglist first.
- */
-int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
- const char *thread_name)
-{
- struct vb2_threadio_data *threadio;
- int ret = 0;
-
- if (q->threadio)
- return -EBUSY;
- if (vb2_is_busy(q))
- return -EBUSY;
- if (WARN_ON(q->fileio))
- return -EBUSY;
-
- threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
- if (threadio == NULL)
- return -ENOMEM;
- threadio->fnc = fnc;
- threadio->priv = priv;
-
- ret = __vb2_init_fileio(q, !q->is_output);
- dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
- if (ret)
- goto nomem;
- q->threadio = threadio;
- threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
- if (IS_ERR(threadio->thread)) {
- ret = PTR_ERR(threadio->thread);
- threadio->thread = NULL;
- goto nothread;
- }
- return 0;
-
-nothread:
- __vb2_cleanup_fileio(q);
-nomem:
- kfree(threadio);
- return ret;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_start);
-
-int vb2_thread_stop(struct vb2_queue *q)
-{
- struct vb2_threadio_data *threadio = q->threadio;
- int err;
-
- if (threadio == NULL)
- return 0;
- threadio->stop = true;
- /* Wake up all pending sleeps in the thread */
- vb2_queue_error(q);
- err = kthread_stop(threadio->thread);
- __vb2_cleanup_fileio(q);
- threadio->thread = NULL;
- kfree(threadio);
- q->threadio = NULL;
- return err;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_stop);
-
/*
* The following functions are not part of the vb2 core API, but are helper
* functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index b73a28a..4b177dc 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -535,6 +535,42 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
unsigned long pgoff,
unsigned long flags);
#endif
+unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file,
+ poll_table *wait);
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblock);
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+ loff_t *ppos, int nonblock);
+
+/*
+ * vb2_thread_fnc - callback function for use with vb2_thread
+ *
+ * This is called whenever a buffer is dequeued in the thread.
+ */
+typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
+
+/**
+ * vb2_thread_start() - start a thread for the given queue.
+ * @q: videobuf queue
+ * @fnc: callback function
+ * @priv: priv pointer passed to the callback function
+ * @thread_name:the name of the thread. This will be prefixed with "vb2-".
+ *
+ * This starts a thread that will queue and dequeue until an error occurs
+ * or @vb2_thread_stop is called.
+ *
+ * This function should not be used for anything else but the videobuf2-dvb
+ * support. If you think you have another good use-case for this, then please
+ * contact the linux-media mailinglist first.
+ */
+int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
+ const char *thread_name);
+
+/**
+ * vb2_thread_stop() - stop the thread for the given queue.
+ * @q: videobuf queue
+ */
+int vb2_thread_stop(struct vb2_queue *q);
/**
* vb2_is_streaming() - return streaming status of the queue
@@ -639,4 +675,11 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
q->last_buffer_dequeued = false;
}
+/*
+ * The following functions are not part of the vb2 core API, but are useful
+ * functions for videobuf2-*.
+ */
+bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
+int vb2_verify_memory_type(struct vb2_queue *q,
+ enum vb2_memory memory, unsigned int type);
#endif /* _MEDIA_VIDEOBUF2_CORE_H */
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 110062e..3cc836f 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -63,42 +63,8 @@ int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
int __must_check vb2_queue_init(struct vb2_queue *q);
void vb2_queue_release(struct vb2_queue *q);
-
-unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblock);
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
- loff_t *ppos, int nonblock);
-
-/*
- * vb2_thread_fnc - callback function for use with vb2_thread
- *
- * This is called whenever a buffer is dequeued in the thread.
- */
-typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
-
-/**
- * vb2_thread_start() - start a thread for the given queue.
- * @q: videobuf queue
- * @fnc: callback function
- * @priv: priv pointer passed to the callback function
- * @thread_name:the name of the thread. This will be prefixed with "vb2-".
- *
- * This starts a thread that will queue and dequeue until an error occurs
- * or @vb2_thread_stop is called.
- *
- * This function should not be used for anything else but the videobuf2-dvb
- * support. If you think you have another good use-case for this, then please
- * contact the linux-media mailinglist first.
- */
-int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
- const char *thread_name);
-
-/**
- * vb2_thread_stop() - stop the thread for the given queue.
- * @q: videobuf queue
- */
-int vb2_thread_stop(struct vb2_queue *q);
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file,
+ poll_table *wait);
/*
* The following functions are not part of the vb2 core API, but are simple
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC PATCH v9 6/6] media: videobuf2: Move vb2_fileio_data and vb2_thread to core part
2015-11-03 10:16 ` [RFC PATCH v9 6/6] media: videobuf2: Move vb2_fileio_data and vb2_thread to core part Junghak Sung
@ 2015-11-05 11:14 ` Hans Verkuil
0 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2015-11-05 11:14 UTC (permalink / raw)
To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
sakari.ailus, pawel
Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon
On 11/03/15 11:16, Junghak Sung wrote:
> Move things related with vb2 file I/O and vb2_thread without doing any
> functional changes. After that, videobuf2-internal.h is removed because
> it is not necessary any more.
>
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Nice to see that videobuf2-internal.h has now disappeared!
One note (something for a separate patch):
> ---
> drivers/media/v4l2-core/videobuf2-core.c | 777 +++++++++++++++++++++++++-
> drivers/media/v4l2-core/videobuf2-internal.h | 161 ------
> drivers/media/v4l2-core/videobuf2-v4l2.c | 630 +--------------------
> include/media/videobuf2-core.h | 43 ++
> include/media/videobuf2-v4l2.h | 38 +-
> 5 files changed, 824 insertions(+), 825 deletions(-)
> delete mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
>
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index 33bdd81..f62c548 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
<snip>
> + q->threadio = NULL;
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(vb2_thread_stop);
> +
> MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
This description should be updated as it is no longer a v4l2 framework but a
more generic media framework.
> MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
> MODULE_LICENSE("GPL");
Regards,
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread