summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2018-05-07 13:06:03 -0700
committerKeith Packard <keithp@keithp.com>2018-05-07 13:06:03 -0700
commit9c028895aa8a6ae1a26e2b9d87f6a9675b97434a (patch)
treeb52c84312f6d82a8d7eba01a0f963cf3747e0406
Video timing measurement tool
Uses a device that signals whether it sees white or black over USB to measure accuracy of frame timing reports. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--Makefile7
-rw-r--r--vidtime.c146
2 files changed, 153 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..65acc36
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+SRCS=vidtime.c
+OBJS=$(SRCS:.c=.o)
+LIBS=-lX11 -lpthread
+CFLAGS=-O0 -g
+
+vidtime: $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
diff --git a/vidtime.c b/vidtime.c
new file mode 100644
index 0000000..59cabf7
--- /dev/null
+++ b/vidtime.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2018 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <X11/Xlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+
+struct monitor {
+ int fd;
+};
+
+static uint64_t vid_clock(void)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return ((uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec);
+}
+
+static void flush(int fd)
+{
+ char buf[1024];
+ int n;
+ int avail;
+ for (;;) {
+ n = ioctl(fd, FIONREAD, &avail);
+ if (n < 0 || avail <= 0)
+ break;
+ read(fd, buf, avail);
+ }
+}
+
+static uint64_t vid_time[2];
+
+static pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t time_cond = PTHREAD_COND_INITIALIZER;
+
+
+static void *monitor_device(void *arg)
+{
+ struct monitor *m = arg;
+ int fd = m->fd;
+ char buf[256];
+ int n;
+ struct termios termios;
+ uint64_t t;
+
+ tcgetattr(fd, &termios);
+ cfmakeraw(&termios);
+ cfsetospeed(&termios, B9600);
+ cfsetispeed(&termios, B9600);
+ tcsetattr(fd, TCSAFLUSH, &termios);
+ flush(fd);
+ write(fd, "E 0\nV 0\n", 8);
+ sleep(1);
+ flush(fd);
+ write(fd, "V 1\n", 4);
+ for (;;) {
+ n = read(fd, buf, sizeof(buf));
+ if (n < 0) {
+ perror("read");
+ return NULL;
+ }
+ t = vid_clock();
+ switch(buf[0]) {
+ case '1':
+ case '0':
+ pthread_mutex_lock(&time_mutex);
+ vid_time[buf[0] - '0'] = t;
+ pthread_cond_signal(&time_cond);
+ pthread_mutex_unlock(&time_mutex);
+ break;
+ }
+ }
+}
+
+#define W 512
+#define H 512
+#define DEV "/dev/ttyACM0"
+
+int main(int argc, char **argv)
+{
+ Display *dpy;
+ int scr;
+ Window root;
+ Window w;
+ GC gc;
+ Pixmap pix;
+ int v = 0;
+ struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 };
+ pthread_t monitor_thread;
+ struct monitor monitor;
+ uint64_t put, got;
+
+ monitor.fd = open(DEV, O_RDWR);
+ if (monitor.fd < 0) {
+ perror(DEV);
+ exit(1);
+ }
+ pthread_create(&monitor_thread, NULL, monitor_device, &monitor);
+
+ dpy = XOpenDisplay(NULL);
+ scr = DefaultScreen(dpy);
+ root = RootWindow(dpy, scr);
+ w = XCreateSimpleWindow(dpy, root, 0, 0, W, H, 0, 0, 0);
+ gc = XCreateGC(dpy, w, 0, NULL);
+ XMapWindow(dpy, w);
+ for (;;) {
+ XSetForeground(dpy, gc, v ? WhitePixel(dpy, scr) : BlackPixel(dpy, scr));
+ XFillRectangle(dpy, w, gc, 0, 0, W, H);
+ put = vid_clock();
+ XFlush(dpy);
+ pthread_mutex_lock(&time_mutex);
+ for (;;) {
+ if (vid_time[v] > put) {
+ got = vid_time[v];
+ break;
+ }
+ pthread_cond_wait (&time_cond, &time_mutex);
+ }
+ pthread_mutex_unlock(&time_mutex);
+ printf("delay %f\n", (got - put) / 1e9);
+ v = 1-v;
+ }
+}