blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

commit 7b147cb0c1eaa728f244cc8390ccfcc3f4aee03a
parent 0f03cc378e6ce48f17a20e409f93bfc11345a6ed
Author: Mattias Andrée <maandree@kth.se>
Date:   Thu, 25 May 2017 15:30:17 +0200

Add blind-from-named and blind-to-named

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
MMakefile | 2++
MTODO | 4++++
Mconfig.mk | 6++++--
Mman/blind-next-frame.1 | 2+-
Asrc/blind-from-named.c | 149+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-to-named.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/common.h | 22++++++++++++++++++++++
7 files changed, 266 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -16,6 +16,7 @@ BIN =\ blind-flip\ blind-flop\ blind-from-image\ + blind-from-named\ blind-from-portable\ blind-from-text\ blind-from-video\ @@ -36,6 +37,7 @@ BIN =\ blind-stack\ blind-time-blur\ blind-to-image\ + blind-to-named\ blind-to-portable\ blind-to-text\ blind-to-video\ diff --git a/TODO b/TODO @@ -9,12 +9,14 @@ blind-apply-map remap pixels (distortion) using the X and Y values, -t for tili blind-apply-kernel apply a convolution matrix. blind-find-frame a graphical tool for locating frames, should highlight key frames, and play audio. Should support both regular videos files and uivf. + finding key frames: ffprobe -show_frames (lists all frames) blind-affine-colour apply an affine transformation to the colour of each pixel, -a for ignoring the alpha channel, -l for linear transformation, -p for transforming each pixel with their own transformation. blind-invert-chroma invert the chroma blind-from-sent convert a sent presentation to a one-frame-per-slide blind video. +blind-interleave framewise interleave videos blind-kirsch https://en.wikipedia.org/wiki/Kirsch_operator blind-gaussian-noise https://en.wikipedia.org/wiki/Gaussian_noise @@ -51,6 +53,8 @@ blind-from-video: add options to: blind-arithm: add support for multiple streams +bug: blind-stack: cannot use file outside /dev/fd/ + Add [-j jobs] to blind-from-video and blind-to-video. Add -f (framewise) to blind-repeat diff --git a/config.mk b/config.mk @@ -5,7 +5,9 @@ VERSION = 1.1 PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man -# You may want to remove -DHAVE_PRCTL and -DHAVE_EPOLL from CPPFLAGS if you are not using Linux. +# You may want to remove -DHAVE_PRCTL, -DHAVE_EPOLL, and +# -DHAVE_SENDFILE from CPPFLAGS if you are not using Linux. CFLAGS = -std=c11 -Wall -pedantic -O2 -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64 -DHAVE_PRCTL -DHAVE_EPOLL +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64\ + -DHAVE_PRCTL -DHAVE_EPOLL -DHAVE_SENDFILE LDFLAGS = -lm -s diff --git a/man/blind-next-frame.1 b/man/blind-next-frame.1 @@ -14,7 +14,7 @@ reads the first frame available in stdin, and prints it, with a head, to stdout. No excess bytes are read, and .B blind-next-frame -can be used again to extract the next next frame. +can be used again to extract the next frame. The width, height, and pixel format of the video must be specified with .IR width , diff --git a/src/blind-from-named.c b/src/blind-from-named.c @@ -0,0 +1,149 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-t decisecs] [-a] ([-f fd] path [command ...] | path)") + +static int +erecv_fd(int sock) +{ + int fd; + char buf[1]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char cms[CMSG_SPACE(sizeof(fd))]; + + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = (caddr_t)cms; + msg.msg_controllen = sizeof(cms); + + switch (recvmsg(sock, &msg, 0)) { + case -1: + eprintf("recvmsg:"); + case 0: + eprintf("recvmsg: connection closed by peer"); + default: + break; + } + + cmsg = CMSG_FIRSTHDR(&msg); + memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + return fd; +} + +#if !defined(HAVE_SENDFILE) +# if !defined(PIPE_BUF) +# define PIPE_BUF BUFSIZ +# endif +static ssize_t +sendfile(int outfd, int infd, off_t *offset, size_t count) +{ + char buf[PIPE_BUF]; + ssize_t r, w, p, ret = 0; + + (void) offset; + (void) count; + + for (;;) { + r = read(infd, buf, sizeof(buf)); + if (r < 0) + eprintf("read <received file>:"); + if (!r) + break; + ret += r; + for (p = 0; p < r; p += w) { + w = write(outfd, buf + p, r - p); + if (w < 0) + eprintf("write <stdout>:"); + } + } + + return ret; +} +#endif + +int +main(int argc, char *argv[]) +{ + struct sockaddr_un addr; + int abstract = 0; + int filedes = -1; + int tries = 10; + int sockfd, fd; + + ARGBEGIN { + case 'a': + abstract = 1; + break; + case 'f': + filedes = etoi_flag('f', UARGF(), 0, INT_MAX); + break; + case 't': + tries = etoi_flag('t', UARGF(), 1, INT_MAX); + break; + default: + usage(); + } ARGEND; + if (argc < 1 || (filedes >= 0 && argc > 1)) + usage(); + if (argc > 0 && filedes < 0) + filedes = 0; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (strlen(argv[0]) + 1 + abstract > sizeof(addr.sun_path)) { + errno = ENAMETOOLONG; + eprintf("%s:", argv[0]); + } + strcpy(addr.sun_path + abstract, argv[0]); + argv++, argc--; + + sockfd = socket(PF_UNIX, SOCK_SEQPACKET, 0); + if (sockfd < 0) + eprintf("socket PF_UNIX SOCK_SEQPACKET:"); + +retry: + if ((connect(sockfd, (const struct sockaddr *)&addr, (size_t)sizeof(addr))) < 0) { + if (--tries) { + usleep((useconds_t)100000L); + goto retry; + } else { + eprintf("bind %s%s%s:", + abstract ? "<abstract:" : "", + addr.sun_path + abstract, + abstract ? ">" : ""); + } + } + + fd = erecv_fd(sockfd); + close(sockfd); + + if (argc) { + if (fd != filedes) { + if (dup2(fd, filedes) < 0) + eprintf("dup2 %i %i:", fd, filedes); + close(fd); + } + execvp(argv[0], argv); + eprintf("execvp %s:", argv[0]); + } + + for (;;) { + switch (sendfile(STDOUT_FILENO, fd, NULL, SIZE_MAX)) { + case 0: + return 0; + case -1: + eprintf("sendfile <stdout> <received file>:"); + default: + break; + } + } +} diff --git a/src/blind-to-named.c b/src/blind-to-named.c @@ -0,0 +1,84 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-a] path") + +static void +esend_fd(int sock, int fd) +{ + char buf[1]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char cms[CMSG_SPACE(sizeof(fd))]; + + buf[0] = 0; + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (caddr_t)cms; + msg.msg_controllen = CMSG_LEN(sizeof(fd)); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + if (sendmsg(sock, &msg, 0) != iov.iov_len) + eprintf("sendmsg:"); +} + +int +main(int argc, char *argv[]) +{ + struct sockaddr_un addr; + int abstract = 0; + int serverfd, connfd; + + ARGBEGIN { + case 'a': + abstract = 1; + break; + default: + usage(); + } ARGEND; + if (argc != 1) + usage(); + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (strlen(argv[0]) + 1 + abstract > sizeof(addr.sun_path)) { + errno = ENAMETOOLONG; + eprintf("%s:", argv[0]); + } + strcpy(addr.sun_path + abstract, argv[0]); + + serverfd = socket(PF_UNIX, SOCK_SEQPACKET, 0); + if (serverfd < 0) + eprintf("socket PF_UNIX SOCK_SEQPACKET:"); + + if (bind(serverfd, (const struct sockaddr *)&addr, (size_t)sizeof(addr)) < 0) + eprintf("bind %s%s%s:", + abstract ? "<abstract:" : "", + addr.sun_path + abstract, + abstract ? ">" : ""); + + if (listen(serverfd, 1) < 0) + eprintf("listen:"); + + connfd = accept(serverfd, NULL, NULL); + if (connfd < 0) + eprintf("accept:"); + + if (*addr.sun_path) + unlink(addr.sun_path); + close(serverfd); + + esend_fd(connfd, STDIN_FILENO); + close(connfd); + return 0; +} diff --git a/src/common.h b/src/common.h @@ -20,7 +20,13 @@ # include <sys/epoll.h> #endif #include <sys/mman.h> +#if defined(HAVE_SENDFILE) +# include <sys/sendfile.h> +#endif #include <sys/stat.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/un.h> #include <sys/wait.h> #include <alloca.h> #include <ctype.h> @@ -35,3 +41,19 @@ #include <string.h> #include <strings.h> #include <unistd.h> + +#ifndef CMSG_ALIGN +# ifdef __sun__ +# define CMSG_ALIGN _CMSG_DATA_ALIGN +# else +# define CMSG_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1)) +# endif +#endif + +#ifndef CMSG_SPACE +# define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len)) +#endif + +#ifndef CMSG_LEN +# define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) +#endif