Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev video(4) changes to support analog tv capture devices:
details: https://anonhg.NetBSD.org/src/rev/8cace29db1d1
branches: trunk
changeset: 759636:8cace29db1d1
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Tue Dec 14 03:25:16 2010 +0000
description:
video(4) changes to support analog tv capture devices:
- support interlacing with VIDIOC_G_FMT
- set V4L2_CAP_TUNER if driver implements the set_tuner/get_tuner
callbacks
- set V4L2_CAP_AUDIO if driver implements the set_audio/get_audio/enum_audio
callbacks
- add support for the following ioctls: VIDIOC_ENUMSTD, VIDIOC_G_STD,
VIDIOC_S_STD, VIDIOC_ENUMINPUT, VIDIOC_G_INPUT, VIDIOC_S_INPUT,
VIDIOC_ENUMAUDIO, VIDIOC_G_AUDIO, VIDIOC_S_AUDIO, VIDIOC_G_TUNER,
VIDIOC_S_TUNER, VIDIOC_G_FREQUENCY, VIDIOC_S_FREQUENCY
- in video_submit_payload(), fix support for signaling sample complete
using frame numbers
- new optional callbacks for drivers: enum_standard, get_standard,
set_standard, enum_input, get_input, set_input, enum_audio, get_audio,
set_audio, get_tuner, set_tuner, get_frequency, set_frequency
for drivers that don't provide enum_standard, get_standard, set_standard,
enum_input, get_input and set_input, the original stub implementations are
provided
diffstat:
sys/dev/video.c | 627 +++++++++++++++++++++++++++++++++++++++++++++++++---
sys/dev/video_if.h | 109 +++++++++-
2 files changed, 696 insertions(+), 40 deletions(-)
diffs (truncated from 879 to 300 lines):
diff -r 1ad8ce018a9a -r 8cace29db1d1 sys/dev/video.c
--- a/sys/dev/video.c Tue Dec 14 03:07:07 2010 +0000
+++ b/sys/dev/video.c Tue Dec 14 03:25:16 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: video.c,v 1.23 2009/12/06 22:42:48 dyoung Exp $ */
+/* $NetBSD: video.c,v 1.24 2010/12/14 03:25:16 jmcneill Exp $ */
/*
* Copyright (c) 2008 Patrick Mahoney <pat%polycrystal.org@localhost>
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: video.c,v 1.23 2009/12/06 22:42:48 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: video.c,v 1.24 2010/12/14 03:25:16 jmcneill Exp $");
#include "video.h"
#if NVIDEO > 0
@@ -224,8 +224,24 @@
struct video_format *);
static void video_format_to_v4l2_format(const struct video_format *,
struct v4l2_format *);
-
-/* V4L2 api functions, typically called from videoioclt() */
+static void v4l2_standard_to_video_standard(v4l2_std_id,
+ enum video_standard *);
+static void video_standard_to_v4l2_standard(enum video_standard,
+ struct v4l2_standard *);
+static void v4l2_input_to_video_input(const struct v4l2_input *,
+ struct video_input *);
+static void video_input_to_v4l2_input(const struct video_input *,
+ struct v4l2_input *);
+static void v4l2_audio_to_video_audio(const struct v4l2_audio *,
+ struct video_audio *);
+static void video_audio_to_v4l2_audio(const struct video_audio *,
+ struct v4l2_audio *);
+static void v4l2_tuner_to_video_tuner(const struct v4l2_tuner *,
+ struct video_tuner *);
+static void video_tuner_to_v4l2_tuner(const struct video_tuner *,
+ struct v4l2_tuner *);
+
+/* V4L2 api functions, typically called from videoioctl() */
static int video_enum_format(struct video_softc *, struct v4l2_fmtdesc *);
static int video_get_format(struct video_softc *,
struct v4l2_format *);
@@ -233,6 +249,22 @@
struct v4l2_format *);
static int video_try_format(struct video_softc *,
struct v4l2_format *);
+static int video_enum_standard(struct video_softc *,
+ struct v4l2_standard *);
+static int video_get_standard(struct video_softc *, v4l2_std_id *);
+static int video_set_standard(struct video_softc *, v4l2_std_id);
+static int video_enum_input(struct video_softc *, struct v4l2_input *);
+static int video_get_input(struct video_softc *, int *);
+static int video_set_input(struct video_softc *, int);
+static int video_enum_audio(struct video_softc *, struct v4l2_audio *);
+static int video_get_audio(struct video_softc *, struct v4l2_audio *);
+static int video_set_audio(struct video_softc *, struct v4l2_audio *);
+static int video_get_tuner(struct video_softc *, struct v4l2_tuner *);
+static int video_set_tuner(struct video_softc *, struct v4l2_tuner *);
+static int video_get_frequency(struct video_softc *,
+ struct v4l2_frequency *);
+static int video_set_frequency(struct video_softc *,
+ struct v4l2_frequency *);
static int video_query_control(struct video_softc *,
struct v4l2_queryctrl *);
static int video_get_control(struct video_softc *,
@@ -586,14 +618,25 @@
dest->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
dest->fmt.pix.width = src->width;
dest->fmt.pix.height = src->height;
- dest->fmt.pix.field = V4L2_FIELD_NONE; /* TODO: for now,
- * just set to
- * progressive */
+ if (VIDEO_INTERLACED(src->interlace_flags))
+ dest->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ else
+ dest->fmt.pix.field = V4L2_FIELD_NONE;
dest->fmt.pix.bytesperline = src->stride;
dest->fmt.pix.sizeimage = src->sample_size;
- dest->fmt.pix.colorspace = 0; /* XXX */
dest->fmt.pix.priv = src->priv;
+ switch (src->color.primaries) {
+ case VIDEO_COLOR_PRIMARIES_SMPTE_170M:
+ dest->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ break;
+ /* XXX */
+ case VIDEO_COLOR_PRIMARIES_UNSPECIFIED:
+ default:
+ dest->fmt.pix.colorspace = 0;
+ break;
+ }
+
switch (src->pixel_format) {
case VIDEO_FORMAT_UYVY:
dest->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
@@ -652,6 +695,23 @@
dest->stride = src->fmt.pix.bytesperline;
dest->sample_size = src->fmt.pix.sizeimage;
+ if (src->fmt.pix.field == V4L2_FIELD_INTERLACED)
+ dest->interlace_flags = VIDEO_INTERLACE_ON;
+ else
+ dest->interlace_flags = VIDEO_INTERLACE_OFF;
+
+ switch (src->fmt.pix.colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ dest->color.primaries =
+ VIDEO_COLOR_PRIMARIES_SMPTE_170M;
+ break;
+ /* XXX */
+ default:
+ dest->color.primaries =
+ VIDEO_COLOR_PRIMARIES_UNSPECIFIED;
+ break;
+ }
+
switch (src->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_UYVY:
dest->pixel_format = VIDEO_FORMAT_UYVY;
@@ -720,6 +780,7 @@
video_format_to_v4l2_format(&vfmt, &fmt);
fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* TODO: only one type for now */
+ fmtdesc->flags = 0;
if (vfmt.pixel_format >= VIDEO_FORMAT_MJPEG)
fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
strlcpy(fmtdesc->description,
@@ -798,6 +859,475 @@
return 0;
}
+static void
+v4l2_standard_to_video_standard(v4l2_std_id stdid,
+ enum video_standard *vstd)
+{
+#define VSTD(id, vid) case (id): *vstd = (vid); break;
+ switch (stdid) {
+ VSTD(V4L2_STD_NTSC_M, VIDEO_STANDARD_NTSC_M)
+ default:
+ *vstd = VIDEO_STANDARD_UNKNOWN;
+ break;
+ }
+#undef VSTD
+}
+
+static void
+video_standard_to_v4l2_standard(enum video_standard vstd,
+ struct v4l2_standard *std)
+{
+ switch (vstd) {
+ case VIDEO_STANDARD_NTSC_M:
+ std->id = V4L2_STD_NTSC_M;
+ strlcpy(std->name, "NTSC-M", sizeof(std->name));
+ std->frameperiod.numerator = 1001;
+ std->frameperiod.denominator = 30000;
+ std->framelines = 525;
+ break;
+ default:
+ std->id = V4L2_STD_UNKNOWN;
+ strlcpy(std->name, "Unknown", sizeof(std->name));
+ break;
+ }
+}
+
+static int
+video_enum_standard(struct video_softc *sc, struct v4l2_standard *std)
+{
+ const struct video_hw_if *hw = sc->hw_if;
+ enum video_standard vstd;
+ int err;
+
+ /* simple webcam drivers don't need to implement this callback */
+ if (hw->enum_standard == NULL) {
+ if (std->index != 0)
+ return EINVAL;
+ std->id = V4L2_STD_UNKNOWN;
+ strlcpy(std->name, "webcam", sizeof(std->name));
+ return 0;
+ }
+
+ v4l2_standard_to_video_standard(std->id, &vstd);
+
+ err = hw->enum_standard(sc->hw_softc, std->index, &vstd);
+ if (err != 0)
+ return err;
+
+ video_standard_to_v4l2_standard(vstd, std);
+
+ return 0;
+}
+
+static int
+video_get_standard(struct video_softc *sc, v4l2_std_id *stdid)
+{
+ const struct video_hw_if *hw = sc->hw_if;
+ struct v4l2_standard std;
+ enum video_standard vstd;
+ int err;
+
+ /* simple webcam drivers don't need to implement this callback */
+ if (hw->get_standard == NULL) {
+ *stdid = V4L2_STD_UNKNOWN;
+ return 0;
+ }
+
+ err = hw->get_standard(sc->hw_softc, &vstd);
+ if (err != 0)
+ return err;
+
+ video_standard_to_v4l2_standard(vstd, &std);
+ *stdid = std.id;
+
+ return 0;
+}
+
+static int
+video_set_standard(struct video_softc *sc, v4l2_std_id stdid)
+{
+ const struct video_hw_if *hw = sc->hw_if;
+ enum video_standard vstd;
+
+ /* simple webcam drivers don't need to implement this callback */
+ if (hw->set_standard == NULL) {
+ if (stdid != V4L2_STD_UNKNOWN)
+ return EINVAL;
+ return 0;
+ }
+
+ v4l2_standard_to_video_standard(stdid, &vstd);
+
+ return hw->set_standard(sc->hw_softc, vstd);
+}
+
+static void
+v4l2_input_to_video_input(const struct v4l2_input *input,
+ struct video_input *vi)
+{
+ vi->index = input->index;
+ strlcpy(vi->name, input->name, sizeof(vi->name));
+ switch (input->type) {
+ case V4L2_INPUT_TYPE_TUNER:
+ vi->type = VIDEO_INPUT_TYPE_TUNER;
+ break;
+ case V4L2_INPUT_TYPE_CAMERA:
+ vi->type = VIDEO_INPUT_TYPE_CAMERA;
+ break;
+ }
+ vi->audiomask = input->audioset;
+ vi->tuner_index = input->tuner;
+ vi->standards = input->std; /* ... values are the same */
+ vi->status = 0;
+ if (input->status & V4L2_IN_ST_NO_POWER)
+ vi->status |= VIDEO_STATUS_NO_POWER;
+ if (input->status & V4L2_IN_ST_NO_SIGNAL)
+ vi->status |= VIDEO_STATUS_NO_SIGNAL;
+ if (input->status & V4L2_IN_ST_NO_COLOR)
+ vi->status |= VIDEO_STATUS_NO_COLOR;
+ if (input->status & V4L2_IN_ST_NO_H_LOCK)
+ vi->status |= VIDEO_STATUS_NO_HLOCK;
+ if (input->status & V4L2_IN_ST_MACROVISION)
+ vi->status |= VIDEO_STATUS_MACROVISION;
+}
+
+static void
+video_input_to_v4l2_input(const struct video_input *vi,
+ struct v4l2_input *input)
+{
+ input->index = vi->index;
+ strlcpy(input->name, vi->name, sizeof(input->name));
+ switch (vi->type) {
+ case VIDEO_INPUT_TYPE_TUNER:
+ input->type = V4L2_INPUT_TYPE_TUNER;
+ break;
+ case VIDEO_INPUT_TYPE_CAMERA:
+ input->type = V4L2_INPUT_TYPE_CAMERA;
+ break;
+ }
+ input->audioset = vi->audiomask;
+ input->tuner = vi->tuner_index;
+ input->std = vi->standards; /* ... values are the same */
+ input->status = 0;
+ if (vi->status & VIDEO_STATUS_NO_POWER)
+ input->status |= V4L2_IN_ST_NO_POWER;
+ if (vi->status & VIDEO_STATUS_NO_SIGNAL)
+ input->status |= V4L2_IN_ST_NO_SIGNAL;
+ if (vi->status & VIDEO_STATUS_NO_COLOR)
+ input->status |= V4L2_IN_ST_NO_COLOR;
+ if (vi->status & VIDEO_STATUS_NO_HLOCK)
+ input->status |= V4L2_IN_ST_NO_H_LOCK;
+ if (vi->status & VIDEO_STATUS_MACROVISION)
+ input->status |= V4L2_IN_ST_MACROVISION;
+}
+
+static int
+video_enum_input(struct video_softc *sc, struct v4l2_input *input)
+{
+ const struct video_hw_if *hw = sc->hw_if;
Home |
Main Index |
Thread Index |
Old Index