Since I recently opened my big fat mouth and suggested that
"kern.video.record" (analogous to kern.audio.record) might be a good idea, I
decided to put together a quick prototype (heavily based on the
kern.audio.record code). This at least roughly works for me but raises some
questions such as:

  * Is uvideo the only driver that can capture video? [I imagine not, but I
    don't really know.]

  * I've taken the same approach as kern.audio.record which is to keep on
    handing out data even when kern.video.record=0 *but* it's harder to work
    out what data we should hand out. At the moment we just pass on whatever
    happened to be in the buffer beforehand (which is clearly not a good
    idea in the long term, but proves the point for now). For uncompressed
    video, handing over (say) an entirely black image is probably easy; for
    compressed video we'd have to think about whether we also want to
    manipulate frame headers etc. It would probably be easier to simply
    intercept the "opening video" event but that would mean that if
    something is already streaming video, setting kern.video.record=0 would
    allow it to keep recording.

Comments welcome, including "this is a terrible idea full stop"!


Laurie



Index: sbin/sysctl/sysctl.c
===================================================================
RCS file: /cvs/src/sbin/sysctl/sysctl.c,v
retrieving revision 1.252
diff -u -p -r1.252 sysctl.c
--- sbin/sysctl/sysctl.c        15 Jul 2020 07:13:56 -0000      1.252
+++ sbin/sysctl/sysctl.c        13 Sep 2020 08:08:57 -0000
@@ -130,6 +130,7 @@ struct ctlname machdepname[] = CTL_MACHD
 #endif
 struct ctlname ddbname[] = CTL_DDB_NAMES;
 struct ctlname audioname[] = CTL_KERN_AUDIO_NAMES;
+struct ctlname videoname[] = CTL_KERN_VIDEO_NAMES;
 struct ctlname witnessname[] = CTL_KERN_WITNESS_NAMES;
 char names[BUFSIZ];
 int lastused;
@@ -219,6 +220,7 @@ void print_sensor(struct sensor *);
 int sysctl_chipset(char *, char **, int *, int, int *);
 #endif
 int sysctl_audio(char *, char **, int *, int, int *);
+int sysctl_video(char *, char **, int *, int, int *);
 int sysctl_witness(char *, char **, int *, int, int *);
 void vfsinit(void);
 
@@ -517,6 +519,11 @@ parse(char *string, int flags)
                        if (len < 0)
                                return;
                        break;
+               case KERN_VIDEO:
+                       len = sysctl_video(string, &bufp, mib, flags, &type);
+                       if (len < 0)
+                               return;
+                       break;
                case KERN_WITNESS:
                        len = sysctl_witness(string, &bufp, mib, flags, &type);
                        if (len < 0)
@@ -1766,6 +1773,7 @@ struct list shmlist = { shmname, KERN_SH
 struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
 struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
 struct list audiolist = { audioname, KERN_AUDIO_MAXID };
+struct list videolist = { audioname, KERN_VIDEO_MAXID };
 struct list witnesslist = { witnessname, KERN_WITNESS_MAXID };
 
 /*
@@ -2813,6 +2821,25 @@ sysctl_audio(char *string, char **bufpp,
                return (-1);
        mib[2] = indx;
        *typep = audiolist.list[indx].ctl_type;
+       return (3);
+}
+
+/*
+ * Handle video support
+ */
+int
+sysctl_video(char *string, char **bufpp, int mib[], int flags, int *typep)
+{
+       int indx;
+
+       if (*bufpp == NULL) {
+               listall(string, &videolist);
+               return (-1);
+       }
+       if ((indx = findname(string, "third", bufpp, &videolist)) == -1)
+               return (-1);
+       mib[2] = indx;
+       *typep = videolist.list[indx].ctl_type;
        return (3);
 }
 
Index: sys/dev/usb/uvideo.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uvideo.c,v
retrieving revision 1.209
diff -u -p -r1.209 uvideo.c
--- sys/dev/usb/uvideo.c        31 Jul 2020 10:49:33 -0000      1.209
+++ sys/dev/usb/uvideo.c        13 Sep 2020 08:08:58 -0000
@@ -386,6 +386,12 @@ struct uvideo_devs {
 #define uvideo_lookup(v, p) \
        ((struct uvideo_devs *)usb_lookup(uvideo_devs, v, p))
 
+/*
+ * Global flag to control if video recording is enabled when the
+ * kern.video.record setting is set to 1.
+ */
+int video_record_enable = 0;
+
 int
 uvideo_enable(void *v)
 {
@@ -2210,7 +2216,8 @@ uvideo_vs_decode_stream_header(struct uv
        /* save sample */
        sample_len = frame_size - sh->bLength;
        if ((fb->offset + sample_len) <= fb->buf_size) {
-               bcopy(frame + sh->bLength, fb->buf + fb->offset, sample_len);
+               if (video_record_enable)
+                       bcopy(frame + sh->bLength, fb->buf + fb->offset, 
sample_len);
                fb->offset += sample_len;
        }
 
@@ -2299,7 +2306,8 @@ uvideo_vs_decode_stream_header_isight(st
                /* save sample */
                sample_len = frame_size;
                if ((fb->offset + sample_len) <= fb->buf_size) {
-                       bcopy(frame, fb->buf + fb->offset, sample_len);
+                       if (video_record_enable)
+                               bcopy(frame, fb->buf + fb->offset, sample_len);
                        fb->offset += sample_len;
                }
        }
@@ -2327,7 +2335,8 @@ uvideo_mmap_queue(struct uvideo_softc *s
        }
 
        /* copy frame to mmap buffer and report length */
-       bcopy(buf, sc->sc_mmap[i].buf, len);
+       if (video_record_enable)
+               bcopy(buf, sc->sc_mmap[i].buf, len);
        sc->sc_mmap[i].v4l2_buf.bytesused = len;
 
        /* timestamp it */
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.379
diff -u -p -r1.379 kern_sysctl.c
--- sys/kern/kern_sysctl.c      1 Sep 2020 01:53:50 -0000       1.379
+++ sys/kern/kern_sysctl.c      13 Sep 2020 08:08:58 -0000
@@ -125,6 +125,7 @@ extern  long numvnodes;
 #if NAUDIO > 0
 extern int audio_record_enable;
 #endif
+extern int video_record_enable;
 
 int allowkmem;
 int allowdt;
@@ -141,6 +142,7 @@ int sysctl_cptime2(int *, u_int, void *,
 #if NAUDIO > 0
 int sysctl_audio(int *, u_int, void *, size_t *, void *, size_t);
 #endif
+int sysctl_video(int *, u_int, void *, size_t *, void *, size_t);
 int sysctl_cpustats(int *, u_int, void *, size_t *, void *, size_t);
 int sysctl_utc_offset(void *, size_t *, void *, size_t);
 
@@ -313,6 +315,7 @@ kern_sysctl(int *name, u_int namelen, vo
                case KERN_FILE:
                case KERN_WITNESS:
                case KERN_AUDIO:
+               case KERN_VIDEO:
                case KERN_CPUSTATS:
                        break;
                default:
@@ -672,6 +675,9 @@ kern_sysctl(int *name, u_int namelen, vo
                return (sysctl_audio(name + 1, namelen - 1, oldp, oldlenp,
                    newp, newlen));
 #endif
+       case KERN_VIDEO:
+               return (sysctl_video(name + 1, namelen - 1, oldp, oldlenp,
+                   newp, newlen));
        case KERN_CPUSTATS:
                return (sysctl_cpustats(name + 1, namelen - 1, oldp, oldlenp,
                    newp, newlen));
@@ -2462,6 +2468,19 @@ sysctl_audio(int *name, u_int namelen, v
        return (sysctl_int(oldp, oldlenp, newp, newlen, &audio_record_enable));
 }
 #endif
+
+int
+sysctl_video(int *name, u_int namelen, void *oldp, size_t *oldlenp,
+    void *newp, size_t newlen)
+{
+       if (namelen != 1)
+               return (ENOTDIR);
+
+       if (name[0] != KERN_VIDEO_RECORD)
+               return (ENOENT);
+
+       return (sysctl_int(oldp, oldlenp, newp, newlen, &video_record_enable));
+}
 
 int
 sysctl_cpustats(int *name, u_int namelen, void *oldp, size_t *oldlenp,
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvs/src/sys/sys/sysctl.h,v
retrieving revision 1.211
diff -u -p -r1.211 sysctl.h
--- sys/sys/sysctl.h    1 Sep 2020 01:53:50 -0000       1.211
+++ sys/sys/sysctl.h    13 Sep 2020 08:08:58 -0000
@@ -189,7 +189,8 @@ struct ctlname {
 #define        KERN_PFSTATUS           86      /* struct: pf status and stats 
*/
 #define        KERN_TIMEOUT_STATS      87      /* struct: timeout status and 
stats */
 #define        KERN_UTC_OFFSET         88      /* int: adjust RTC time to UTC 
*/
-#define        KERN_MAXID              89      /* number of valid kern ids */
+#define        KERN_VIDEO              89      /* struct: video properties */
+#define        KERN_MAXID              90      /* number of valid kern ids */
 
 #define        CTL_KERN_NAMES { \
        { 0, 0 }, \
@@ -281,6 +282,7 @@ struct ctlname {
        { "pfstatus", CTLTYPE_STRUCT }, \
        { "timeout_stats", CTLTYPE_STRUCT }, \
        { "utc_offset", CTLTYPE_INT }, \
+       { "video", CTLTYPE_STRUCT }, \
 }
 
 /*
@@ -318,6 +320,17 @@ struct ctlname {
 #define KERN_AUDIO_MAXID       2
 
 #define CTL_KERN_AUDIO_NAMES { \
+       { 0, 0 }, \
+       { "record", CTLTYPE_INT }, \
+}
+
+/*
+ * KERN_VIDEO
+ */
+#define KERN_VIDEO_RECORD      1
+#define KERN_VIDEO_MAXID       2
+
+#define CTL_KERN_VIDEO_NAMES { \
        { 0, 0 }, \
        { "record", CTLTYPE_INT }, \
 }

Reply via email to