blind

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

commit e7d073bf6fa91c43753ab67644d067e2ce5881a7
parent 687e7aa9abf91f1bade59213a8b53f9bb4ec4186
Author: Mattias Andrée <maandree@kth.se>
Date:   Sat, 13 May 2017 13:52:29 +0200

Add blind-to-portable and blind-from-portable

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

Diffstat:
MMakefile | 2++
MTODO | 7++++++-
Asrc/blind-from-portable.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-to-portable.c | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/util/endian.h | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 331 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile @@ -16,6 +16,7 @@ BIN =\ blind-flip\ blind-flop\ blind-from-image\ + blind-from-portable\ blind-from-text\ blind-from-video\ blind-gauss-blur\ @@ -34,6 +35,7 @@ BIN =\ blind-stack\ blind-time-blur\ blind-to-image\ + blind-to-portable\ blind-to-text\ blind-to-video\ blind-translate\ diff --git a/TODO b/TODO @@ -14,7 +14,7 @@ blind-affine-colour apply an affine transformation to the colour of each pixel, -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-from-sent convert a sent presentation to a one-frame-per-slide blind video. blind-from-video: add options to: * just run ffmpeg just print the output @@ -26,6 +26,11 @@ blind-from-video: add options to: Add [-j jobs] to blind-from-video and blind-to-video. +Generate a header file with the appropriate values for USING_BINARY32, USING_BINARY64. +long double is slightly faster than long. +long double (xyza q) could be added as another format. +unsigned char (xyza 8) could be added as another format, it's probably good for previewing + HELP REQUIRED: blind-z-map create a Z-map video from two or more videos diff --git a/src/blind-from-portable.c b/src/blind-from-portable.c @@ -0,0 +1,117 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include <alloca.h> +#include <math.h> +#include <string.h> + +USAGE("[-s]") + +#define USING_BINARY32 0 +#define USING_BINARY64 0 + +#define CONV(ITYPE, SITYPE, OTYPE, EXPONENT, HA2EXPONENT, FRACTION, SUFFIX)\ + do {\ + static int cache_i = 0;\ + static ITYPE cache_in[] = {0, 0, 0, 0};\ + static OTYPE cache_out[] = {0, 0, 0, 0};\ + ITYPE exponent, fraction, signb;\ + SITYPE sexponent;\ + OTYPE ret, dexponent;\ + if (portable == cache_in[cache_i]) {\ + ret = cache_out[cache_i++];\ + cache_i &= 3;\ + return ret;\ + }\ + signb = portable >> (EXPONENT + FRACTION);\ + exponent = (portable >> FRACTION) ^ (signb << EXPONENT);\ + fraction = portable & (((ITYPE)1 << FRACTION) - 1);\ + if (!exponent) {\ + if (!fraction) {\ + ret = (OTYPE)0.0;\ + } else {\ + sexponent = 1 - HA2EXPONENT - FRACTION;\ + dexponent = (OTYPE)sexponent;\ + ret = (ITYPE)fraction;\ + ret *= pow##SUFFIX((OTYPE)2.0, dexponent);\ + }\ + } else if (exponent + 1 == (ITYPE)1 << EXPONENT) {\ + ret = (OTYPE)(fraction ? NAN : INFINITY);\ + } else {\ + fraction |= (ITYPE)1 << FRACTION;\ + sexponent = (SITYPE)exponent;\ + sexponent -= HA2EXPONENT + FRACTION;\ + dexponent = (OTYPE)sexponent;\ + ret = (ITYPE)fraction;\ + ret *= pow##SUFFIX((OTYPE)2.0, dexponent);\ + }\ + ret = signb ? -ret : ret;\ + cache_out[cache_i++] = ret;\ + cache_i &= 3;\ + return ret;\ + } while (0) + +#define PROCESS(ITYPE, OTYPE, BITS)\ + do {\ + size_t i, n;\ + ITYPE *ibuf = (ITYPE *)(stream->buf);\ + OTYPE *obuf = sizeof(ITYPE) == sizeof(OTYPE) ? (OTYPE *)(stream->buf)\ + : alloca(sizeof(stream->buf) / sizeof(ITYPE) * sizeof(OTYPE));\ + strict *= !USING_BINARY##BITS;\ + if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\ + eprintf("-s is required on this machine\n");\ + do {\ + n = stream->ptr / sizeof(ITYPE);\ + if (strict) {\ + for (i = 0; i < n; i++)\ + obuf[i] = conv_##OTYPE(le##BITS##toh(ibuf[i]));\ + } else {\ + for (i = 0; i < n; i++)\ + obuf[i] = *(OTYPE *)&(ITYPE){le##BITS##toh(ibuf[i])};\ + }\ + ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE), "<stdout>");\ + n *= sizeof(ITYPE);\ + memmove(stream->buf, stream->buf + n, stream->ptr -= n);\ + } while (eread_stream(stream, SIZE_MAX));\ + if (stream->ptr)\ + eprintf("%s: incomplete frame\n", stream->file);\ + } while (0) + +static double conv_double(uint64_t portable) {CONV(uint64_t, int64_t, double, 11, 1023, 52,);} +static float conv_float (uint32_t portable) {CONV(uint32_t, int32_t, float, 8, 127, 23, f);} + +static void process_xyza (struct stream *stream, int strict) {PROCESS(uint64_t, double, 64);} +static void process_xyzaf(struct stream *stream, int strict) {PROCESS(uint32_t, float, 32);} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + int strict = 0; + void (*process)(struct stream *stream, int strict); + + ARGBEGIN { + case 's': + strict = 1; + break; + default: + usage(); + } ARGEND; + if (argc) + usage(); + + eopen_stream(&stream, NULL); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_xyza; + else if (!strcmp(stream.pixfmt, "xyza f")) + process = process_xyzaf; + else + eprintf("pixel format %s is not supported\n", stream.pixfmt); + + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + process(&stream, strict); + return 0; +} diff --git a/src/blind-to-portable.c b/src/blind-to-portable.c @@ -0,0 +1,128 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include <alloca.h> +#include <math.h> +#include <string.h> + +USAGE("[-s]") + +#define USING_BINARY32 0 +#define USING_BINARY64 0 + +#define CONV(ITYPE, OTYPE, SOTYPE, EXPONENT, HA2EXPONENT, FRACTION, SUFFIX)\ + do {\ + static int cache_i = 0;\ + static ITYPE cache_in[] = {0, 0, 0, 0};\ + static OTYPE cache_out[] = {0, 0, 0, 0};\ + OTYPE signb, fraction, ret;\ + SOTYPE exponent;\ + ITYPE u, dexponent;\ + if (host == cache_in[cache_i]) {\ + ret = cache_out[cache_i++];\ + cache_i &= 3;\ + return ret;\ + }\ + signb = signbit(host);\ + u = signb ? -host : host;\ + if (isnan(host) || !isfinite(host)) {\ + ret = ((((OTYPE)1 << EXPONENT) - 1) << FRACTION) | !isinf(host);\ + } else if (u == (ITYPE)0.0) {\ + ret = 0;\ + } else {\ + dexponent = log2##SUFFIX(u);\ + exponent = (SOTYPE)dexponent;\ + if (u == pow##SUFFIX(2.0, (ITYPE)exponent)) {\ + exponent += HA2EXPONENT;\ + fraction = 0;\ + } else {\ + /* TODO subnormals are a bit rounded off */\ + u *= pow##SUFFIX(2.0, (ITYPE)(FRACTION + 1 - exponent));\ + fraction = u;\ + while (fraction >= (OTYPE)2 << FRACTION) {\ + fraction >>= 1;\ + exponent += 1;\ + }\ + fraction &= ((OTYPE)1 << FRACTION) - 1;\ + exponent += HA2EXPONENT - 1;\ + }\ + if (exponent < 1) {\ + /* TODO subnormal result */\ + exponent = 0;\ + fraction = 0;\ + } else if (exponent >= ((SOTYPE)1 << EXPONENT) - (SOTYPE)1) { \ + exponent = ((SOTYPE)1 << EXPONENT) - (SOTYPE)1;\ + fraction = 0;\ + }\ + ret = (exponent << FRACTION) + fraction;\ + }\ + ret |= signb << (FRACTION + EXPONENT);\ + cache_out[cache_i++] = ret;\ + cache_i &= 3;\ + return ret;\ + } while (0) + +#define PROCESS(ITYPE, OTYPE, BITS)\ + do {\ + size_t i, n;\ + ITYPE *ibuf = (ITYPE *)(stream->buf);\ + OTYPE *obuf = sizeof(ITYPE) == sizeof(OTYPE) ? (OTYPE *)(stream->buf)\ + : alloca(sizeof(stream->buf) / sizeof(ITYPE) * sizeof(OTYPE));\ + strict *= !USING_BINARY##BITS;\ + if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\ + eprintf("-s is required on this machine\n");\ + do {\ + n = stream->ptr / sizeof(ITYPE);\ + if (strict) {\ + for (i = 0; i < n; i++)\ + obuf[i] = htole##BITS(conv_##ITYPE(ibuf[i]));\ + } else {\ + for (i = 0; i < n; i++)\ + obuf[i] = htole##BITS(*(OTYPE *)&ibuf[i]);\ + }\ + ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE), "<stdout>");\ + n *= sizeof(ITYPE);\ + memmove(stream->buf, stream->buf + n, stream->ptr -= n);\ + } while (eread_stream(stream, SIZE_MAX));\ + if (stream->ptr)\ + eprintf("%s: incomplete frame\n", stream->file);\ + } while (0) + +static uint64_t conv_double(double host) {CONV(double, uint64_t, int64_t, 11, 1023, 52,);} +static uint32_t conv_float (float host) {CONV(float, uint32_t, int32_t, 8, 127, 23, f);} + +static void process_xyza (struct stream *stream, int strict) {PROCESS(double, uint64_t, 64);} +static void process_xyzaf(struct stream *stream, int strict) {PROCESS(float, uint32_t, 32);} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + int strict = 0; + void (*process)(struct stream *stream, int strict); + + ARGBEGIN { + case 's': + strict = 1; + break; + default: + usage(); + } ARGEND; + if (argc) + usage(); + + eopen_stream(&stream, NULL); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_xyza; + else if (!strcmp(stream.pixfmt, "xyza f")) + process = process_xyzaf; + else + eprintf("pixel format %s is not supported\n", stream.pixfmt); + + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + process(&stream, strict); + return 0; +} diff --git a/src/util/endian.h b/src/util/endian.h @@ -24,6 +24,44 @@ blind_htole16(uint16_t h) } # endif +# if !defined(htole32) +# define htole32 blind_htole32 +static inline uint32_t +blind_htole32(uint32_t h) +{ + union { + unsigned char bytes[4]; + uint32_t value; + } d; + d.bytes[0] = h; + d.bytes[1] = h >> 8; + d.bytes[2] = h >> 16; + d.bytes[3] = h >> 24; + return d.value; +} +# endif + +# if !defined(htole64) +# define htole64 blind_htole64 +static inline uint64_t +blind_htole64(uint64_t h) +{ + union { + unsigned char bytes[8]; + uint64_t value; + } d; + d.bytes[0] = h; + d.bytes[1] = h >> 8; + d.bytes[2] = h >> 16; + d.bytes[3] = h >> 24; + d.bytes[4] = h >> 32; + d.bytes[5] = h >> 40; + d.bytes[6] = h >> 48; + d.bytes[7] = h >> 56; + return d.value; +} +# endif + # if !defined(le16toh) # if defined(letoh16) # define le16toh letoh16 @@ -38,6 +76,46 @@ blind_le16toh(uint16_t le) # endif # endif +# if !defined(le32toh) +# if defined(letoh32) +# define le32toh letoh32 +# else +# define le32toh blind_le32toh +static inline uint32_t +blind_le32toh(uint32_t le) +{ + unsigned char *bytes = (unsigned char *)&le; + return ((uint32_t)(bytes[3]) << 24) | + ((uint32_t)(bytes[2]) << 16) | + ((uint32_t)(bytes[1]) << 8) | + (uint32_t)(bytes[0]); +} +# endif +# endif + +# if !defined(le64toh) +# if defined(letoh64) +# define le64toh letoh64 +# else +# define le64toh blind_le64toh +static inline uint64_t +blind_le64toh(uint64_t le) +{ + unsigned char *bytes = (unsigned char *)&le; + return ((uint64_t)(bytes[7]) << 56) | + ((uint64_t)(bytes[6]) << 48) | + ((uint64_t)(bytes[5]) << 40) | + ((uint64_t)(bytes[4]) << 32) | + ((uint64_t)(bytes[3]) << 24) | + ((uint64_t)(bytes[2]) << 16) | + ((uint64_t)(bytes[1]) << 8) | + (uint64_t)(bytes[0]); +} +# endif +# endif + #elif defined(HAVE_OPENBSD_ENDIAN) # define le16toh letoh16 +# define le32toh letoh32 +# define le64toh letoh64 #endif