commit b7a82c980fe7e0c1f9029b55be97422428d65d5a
parent af28793090a32460a558914d4b5379498b712302
Author: Mattias Andrée <maandree@kth.se>
Date: Wed, 11 Jan 2017 09:11:51 +0100
Clean up code
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
38 files changed, 745 insertions(+), 1024 deletions(-)
diff --git a/Makefile b/Makefile
@@ -32,10 +32,11 @@ all: $(BIN)
%: %.o util.o stream.o
$(CC) $(LDFLAGS) -o $@ $^
-%.o: src/%.c src/*.h
+%.o: src/%.c src/*.h src/*/*.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
clean:
-rm $(BIN) $(BIN:=.o) util.o stream.o
.PHONY: all clean
+.PRECIOUS: util.o stream.o
diff --git a/src/arg.h b/src/arg.h
@@ -75,4 +75,14 @@ extern char *argv0;
#define LNGARG() &argv[0][0]
+#define EARG() EARGF(usage())
+
+#define ENOFLAGS(...) ARGBEGIN {\
+ default:\
+ usage();\
+ } ARGEND;\
+ if (__VA_ARGS__)\
+ usage()
+
+
#endif
diff --git a/src/stream.c b/src/stream.c
@@ -4,6 +4,7 @@
#include <sys/stat.h>
#include <errno.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -133,7 +134,60 @@ eninf_check_fd(int status, int fd, const char *file)
{
struct stat st;
if (fstat(fd, &st))
- eprintf("fstat %s:", file);
+ enprintf(status, "fstat %s:", file);
if (S_ISREG(st.st_mode))
- eprintf("%s is a regular file, refusing infinite write\n");
+ enprintf(status, "%s is a regular file, refusing infinite write\n");
+}
+
+
+int
+check_frame_size(size_t width, size_t height, size_t pixel_size)
+{
+ if (!width || !height || !pixel_size)
+ return 1;
+ if (width > SIZE_MAX / height)
+ return 0;
+ if (width * height > SIZE_MAX / pixel_size)
+ return 0;
+ return 1;
+}
+
+void
+encheck_frame_size(int status, size_t width, size_t height, size_t pixel_size, const char *prefix, const char *fname)
+{
+ if (!check_frame_size(width, height, pixel_size))
+ enprintf(status, "%s: %s%svideo frame is too large\n",
+ prefix ? prefix : "", (prefix && *prefix) ? " " : "", fname);
+}
+
+
+void
+encheck_compat(int status, const struct stream *a, const struct stream *b)
+{
+ if (a->width != b->width || a->height != b->height)
+ eprintf("videos do not have the same geometry\n");
+ if (strcmp(a->pixfmt, b->pixfmt))
+ eprintf("videos use incompatible pixel formats\n");
+}
+
+
+int
+enread_frame(int status, struct stream *stream, void *buf, size_t n)
+{
+ char *buffer = buf;
+ ssize_t r;
+ for (; stream->ptr < n; stream->ptr += (size_t)r) {
+ r = read(stream->fd, buffer + stream->ptr, n - stream->ptr);
+ if (r < 0) {
+ eprintf("read %s:", stream->file);
+ } else if (r == 0) {
+ if (!stream->ptr)
+ break;
+ eprintf("%s: incomplete frame", stream->file);
+ }
+ }
+ if (!stream->ptr)
+ return 0;
+ stream->ptr = 0;
+ return 1;
}
diff --git a/src/stream.h b/src/stream.h
@@ -2,6 +2,17 @@
#include <stddef.h>
#include <stdio.h>
+#define einit_stream(...) eninit_stream(1, __VA_ARGS__)
+#define eset_pixel_size(...) enset_pixel_size(1, __VA_ARGS__)
+#define eread_stream(...) enread_stream(1, __VA_ARGS__)
+#define einf_check_fd(...) eninf_check_fd(1, __VA_ARGS__)
+#define echeck_frame_size(...) encheck_frame_size(1, __VA_ARGS__)
+#define echeck_compat(...) encheck_compat(1, __VA_ARGS__)
+#define eread_frame(...) enread_frame(1, __VA_ARGS__)
+
+#define enread_row(...) enread_frame(__VA_ARGS__)
+#define eread_row(...) eread_frame(__VA_ARGS__)
+
struct stream
{
size_t frames;
@@ -15,42 +26,30 @@ struct stream
const char *file;
};
-
void eninit_stream(int status, struct stream *stream);
-
-static inline void
-einit_stream(struct stream *stream)
-{
- eninit_stream(1, stream);
-}
-
-
int set_pixel_size(struct stream *stream);
void enset_pixel_size(int status, struct stream *stream);
-
-static inline void
-eset_pixel_size(struct stream *stream)
-{
- enset_pixel_size(1, stream);
-}
-
-
void fprint_stream_head(FILE *fp, struct stream *stream);
-
-
size_t enread_stream(int status, struct stream *stream, size_t n);
-
-static inline size_t
-eread_stream(struct stream *stream, size_t n)
-{
- return enread_stream(1, stream, n);
-}
-
-
void eninf_check_fd(int status, int fd, const char *file);
-
-static inline void
-einf_check_fd(int fd, const char *file)
-{
- eninf_check_fd(1, fd, file);
-}
+int check_frame_size(size_t width, size_t height, size_t pixel_size);
+void encheck_frame_size(int status, size_t width, size_t height, size_t pixel_size, const char *prefix, const char *fname);
+void encheck_compat(int status, const struct stream *a, const struct stream *b);
+int enread_frame(int status, struct stream *stream, void *buf, size_t n);
+
+#define EACH_FRAME_SEGMENTED(stream, process)\
+ do {\
+ size_t size__, f__, r__, n__;\
+ echeck_frame_size((stream)->width, (stream)->height, (stream)->pixel_size, 0, (stream)->file);\
+ size__ = (stream)->height * (stream)->width * (stream)->pixel_size;\
+ for (f__ = 0; f__ < (stream)->frames; f__++) {\
+ for (n__ = size__; n__; n__ -= r__) {\
+ if (!eread_stream((stream), n__))\
+ eprintf("%s: file is shorter than expected\n", (stream)->file);\
+ r__ = (stream)->ptr - ((stream)->ptr % (stream)->pixel_size);\
+ (process)((stream), r__, f__);\
+ ewriteall(STDOUT_FILENO, (stream)->buf, r__, "<stdout>");\
+ memmove((stream)->buf, (stream)->buf + r__, (stream)->ptr -= r__);\
+ }\
+ }\
+ } while (0)
diff --git a/src/util.c b/src/util.c
@@ -9,12 +9,16 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <unistd.h>
char *argv0;
-static void
-xvprintf(const char *fmt, va_list ap)
+void
+weprintf(const char *fmt, ...)
{
+ va_list ap;
+ va_start(ap, fmt);
+
if (argv0 && strncmp(fmt, "usage", strlen("usage")))
fprintf(stderr, "%s: ", argv0);
@@ -24,39 +28,7 @@ xvprintf(const char *fmt, va_list ap)
fputc(' ', stderr);
perror(NULL);
}
-}
-void
-eprintf(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- xvprintf(fmt, ap);
- va_end(ap);
-
- exit(1);
-}
-
-void
-enprintf(int status, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- xvprintf(fmt, ap);
- va_end(ap);
-
- exit(status);
-}
-
-void
-weprintf(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- xvprintf(fmt, ap);
va_end(ap);
}
@@ -132,39 +104,17 @@ erange:
int
-fshut(FILE *fp, const char *fname)
+writeall(int fd, void *buf, size_t n)
{
- int ret = 0;
-
- /* fflush() is undefined for input streams by ISO C,
- * but not POSIX 2008 if you ignore ISO C overrides.
- * Leave it unchecked and rely on the following
- * functions to detect errors.
- */
- fflush(fp);
-
- if (ferror(fp) && !ret) {
- weprintf("ferror %s:", fname);
- ret = 1;
- }
-
- if (fclose(fp) && !ret) {
- weprintf("fclose %s:", fname);
- ret = 1;
+ char *buffer = buf;
+ size_t ptr = 0;
+ ssize_t r;
+ while (ptr < n) {
+ r = write(STDOUT_FILENO, buffer, n);
+ if (r < 0)
+ return -1;
+ buffer += (size_t)ptr;
+ n -= (size_t)ptr;
}
-
- return ret;
-}
-
-void
-enfshut(int status, FILE *fp, const char *fname)
-{
- if (fshut(fp, fname))
- exit(status);
-}
-
-void
-efshut(FILE *fp, const char *fname)
-{
- enfshut(1, fp, fname);
+ return 0;
}
diff --git a/src/util.h b/src/util.h
@@ -1,99 +1,17 @@
/* See LICENSE file for copyright and license details. */
-#include <errno.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define D65_XYY_X 0.312726871026564878786047074755
-#define D65_XYY_Y 0.329023206641284038376227272238
+#include "arg.h"
#define ELEMENTSOF(ARRAY) (sizeof(ARRAY) / sizeof(*(ARRAY)))
-void eprintf(const char *fmt, ...);
-void enprintf(int status, const char *fmt, ...);
-void weprintf(const char *fmt, ...);
-
-int tollu(const char *s, unsigned long long int min, unsigned long long int max, unsigned long long int *out);
-int tolli(const char *s, long long int min, long long int max, long long int *out);
-#define DEF_STR_TO_INT(FNAME, INTTYPE, INTER_FNAME, INTER_INTTYPE)\
- static inline int\
- FNAME(const char *s, INTTYPE min, INTTYPE max, INTTYPE *out)\
- {\
- INTER_INTTYPE inter;\
- if (INTER_FNAME(s, (INTER_INTTYPE)min, (INTER_INTTYPE)max, &inter))\
- return -1;\
- *out = (INTTYPE)inter;\
- return 0;\
- }
-DEF_STR_TO_INT(tolu, unsigned long int, tollu, unsigned long long int)
-DEF_STR_TO_INT(tou, unsigned int, tollu, unsigned long long int)
-DEF_STR_TO_INT(toli, long int, tolli, long long int)
-DEF_STR_TO_INT(toi, int, tolli, long long int)
-#undef DEF_STR_TO_INT
-#define tozu tolu
-#define tozi toli
-#define toju tollu
-#define toji tolli
-
-static inline int
-tolf(const char *s, double *out)
-{
- char *end;
- errno = 0;
- *out = strtod(s, &end);
- if (errno) {
- return -1;
- } else if (*end) {
- errno = EINVAL;
- return -1;
- }
- return 0;
-}
-
-int fshut(FILE *fp, const char *fname);
-void enfshut(int status, FILE *fp, const char *fname);
-void efshut(FILE *fp, const char *fname);
-
-static inline double
-srgb_encode(double t)
-{
- double sign = 1;
- if (t < 0) {
- t = -t;
- sign = -1;
- }
- t = t <= 0.0031306684425217108 ? 12.92 * t : 1.055 * pow(t, 1 / 2.4) - 0.055;
- return t * sign;
-}
-
-static inline double
-srgb_decode(double t)
-{
- double sign = 1;
- if (t < 0) {
- t = -t;
- sign = -1;
- }
- t = t <= 0.0031306684425217108 * 12.92 ? t / 12.92 : pow((t + 0.055) / 1.055, 2.4);
- return t * sign;
-}
-
-static inline void
-ciexyz_to_srgb(double x, double y, double z, double *r, double *g, double *b)
-{
-#define MULTIPLY(CX, CY, CZ) ((CX) * x + (CY) * y + (CZ) * z)
- *r = MULTIPLY(3.240446254647737500675930277794, -1.537134761820080575134284117667, -0.498530193022728718155178739835);
- *g = MULTIPLY(-0.969266606244679751469561779231, 1.876011959788370209167851498933, 0.041556042214430065351304932619);
- *b = MULTIPLY(0.055643503564352832235773149705, -0.204026179735960239147729566866, 1.057226567722703292062647051353);
-#undef MULTIPLY
-}
-
-static inline void
-srgb_to_ciexyz(double r, double g, double b, double *x, double *y, double *z)
-{
-#define MULTIPLY(CR, CG, CB) ((CR) * r + (CG) * g + (CB) * b)
- *x = MULTIPLY(0.412457445582367576708548995157, 0.357575865245515878143578447634, 0.180437247826399665973085006954);
- *y = MULTIPLY(0.212673370378408277403536885686, 0.715151730491031756287156895269, 0.072174899130559869164791564344);
- *z = MULTIPLY(0.019333942761673460208893260415, 0.119191955081838593666354597644, 0.950302838552371742508739771438);
-#undef MULTIPLY
-}
+#define USAGE(SYNOPSIS)\
+ static void usage(void)\
+ { eprintf("usage: %s%s%s\n", argv0, SYNOPSIS ? " " : "", SYNOPSIS); }
+
+#include "util/eprintf.h"
+#include "util/efflush.h"
+#include "util/fshut.h"
+#include "util/eopen.h"
+#include "util/emalloc.h"
+#include "util/to.h"
+#include "util/colour.h"
+#include "util/io.h"
diff --git a/src/util/colour.h b/src/util/colour.h
@@ -0,0 +1,49 @@
+/* See LICENSE file for copyright and license details. */
+#include <math.h>
+
+#define D65_XYY_X 0.312726871026564878786047074755
+#define D65_XYY_Y 0.329023206641284038376227272238
+
+static inline double
+srgb_encode(double t)
+{
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t <= 0.0031306684425217108 ? 12.92 * t : 1.055 * pow(t, 1 / 2.4) - 0.055;
+ return t * sign;
+}
+
+static inline double
+srgb_decode(double t)
+{
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t <= 0.0031306684425217108 * 12.92 ? t / 12.92 : pow((t + 0.055) / 1.055, 2.4);
+ return t * sign;
+}
+
+static inline void
+ciexyz_to_srgb(double x, double y, double z, double *r, double *g, double *b)
+{
+#define MULTIPLY(CX, CY, CZ) ((CX) * x + (CY) * y + (CZ) * z)
+ *r = MULTIPLY(3.240446254647737500675930277794, -1.537134761820080575134284117667, -0.498530193022728718155178739835);
+ *g = MULTIPLY(-0.969266606244679751469561779231, 1.876011959788370209167851498933, 0.041556042214430065351304932619);
+ *b = MULTIPLY(0.055643503564352832235773149705, -0.204026179735960239147729566866, 1.057226567722703292062647051353);
+#undef MULTIPLY
+}
+
+static inline void
+srgb_to_ciexyz(double r, double g, double b, double *x, double *y, double *z)
+{
+#define MULTIPLY(CR, CG, CB) ((CR) * r + (CG) * g + (CB) * b)
+ *x = MULTIPLY(0.412457445582367576708548995157, 0.357575865245515878143578447634, 0.180437247826399665973085006954);
+ *y = MULTIPLY(0.212673370378408277403536885686, 0.715151730491031756287156895269, 0.072174899130559869164791564344);
+ *z = MULTIPLY(0.019333942761673460208893260415, 0.119191955081838593666354597644, 0.950302838552371742508739771438);
+#undef MULTIPLY
+}
diff --git a/src/util/efflush.h b/src/util/efflush.h
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+
+#define efflush(...) enfflush(1, __VA_ARGS__)
+
+static inline void
+enfflush(int status, FILE *fp, const char *fname)
+{
+ fflush(fp);
+ if (ferror(fp))
+ enprintf(status, "%s:", fname);
+}
diff --git a/src/util/emalloc.h b/src/util/emalloc.h
@@ -0,0 +1,23 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdlib.h>
+
+#define emalloc(...) enmalloc(1, __VA_ARGS__)
+#define ecalloc(...) encalloc(1, __VA_ARGS__)
+
+static inline void *
+enmalloc(int status, size_t n)
+{
+ void *ptr = malloc(n);
+ if (!ptr)
+ enprintf(status, "malloc: out of memory\n");
+ return ptr;
+}
+
+static inline void *
+encalloc(int status, size_t n, size_t m)
+{
+ void *ptr = calloc(n, m);
+ if (!ptr)
+ enprintf(status, "malloc: out of memory\n");
+ return ptr;
+}
diff --git a/src/util/eopen.h b/src/util/eopen.h
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include <fcntl.h>
+
+#define eopen(...) enopen(1, __VA_ARGS__)
+#define enopen(...) xenopen(__VA_ARGS__, 0)
+
+static inline int
+xenopen(int status, const char *path, int flags, int mode, ...)
+{
+ int fd = open(path, flags, mode);
+ if (fd < 0)
+ enprintf(status, "open %s:", path);
+ return fd;
+}
diff --git a/src/util/eprintf.h b/src/util/eprintf.h
@@ -0,0 +1,10 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdlib.h>
+
+void weprintf(const char *fmt, ...);
+
+#define eprintf(...)\
+ (weprintf(__VA_ARGS__), exit(1))
+
+#define enprintf(status, ...)\
+ (weprintf(__VA_ARGS__), exit(status))
diff --git a/src/util/fshut.h b/src/util/fshut.h
@@ -0,0 +1,36 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+
+#define efshut(...) enfshut(1, __VA_ARGS__)
+
+static inline int
+fshut(FILE *fp, const char *fname)
+{
+ int ret = 0;
+
+ /* fflush() is undefined for input streams by ISO C,
+ * but not POSIX 2008 if you ignore ISO C overrides.
+ * Leave it unchecked and rely on the following
+ * functions to detect errors.
+ */
+ fflush(fp);
+
+ if (ferror(fp) && !ret) {
+ weprintf("ferror %s:", fname);
+ ret = 1;
+ }
+
+ if (fclose(fp) && !ret) {
+ weprintf("fclose %s:", fname);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static inline void
+enfshut(int status, FILE *fp, const char *fname)
+{
+ if (fshut(fp, fname))
+ exit(status);
+}
diff --git a/src/util/io.h b/src/util/io.h
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+
+#define ewriteall(...) enwriteall(1, __VA_ARGS__)
+
+int writeall(int fd, void *buf, size_t n);
+
+static inline void
+enwriteall(int status, int fd, void *buf, size_t n, const char *fname)
+{
+ if (writeall(fd, buf, n))
+ enprintf(status, "write %s:", fname);
+}
diff --git a/src/util/to.h b/src/util/to.h
@@ -0,0 +1,135 @@
+/* See LICENSE file for copyright and license details. */
+#include <errno.h>
+#include <stdlib.h>
+
+int tollu(const char *s, unsigned long long int min, unsigned long long int max, unsigned long long int *out);
+int tolli(const char *s, long long int min, long long int max, long long int *out);
+#define DEF_STR_TO_INT(FNAME, INTTYPE, INTER_FNAME, INTER_INTTYPE, PRI)\
+ static inline int\
+ FNAME(const char *s, INTTYPE min, INTTYPE max, INTTYPE *out)\
+ {\
+ INTER_INTTYPE inter;\
+ if (INTER_FNAME(s, (INTER_INTTYPE)min, (INTER_INTTYPE)max, &inter))\
+ return -1;\
+ *out = (INTTYPE)inter;\
+ return 0;\
+ }
+DEF_STR_TO_INT(tolu, unsigned long int, tollu, unsigned long long int, "lu")
+DEF_STR_TO_INT(tou, unsigned int, tollu, unsigned long long int, "u")
+DEF_STR_TO_INT(toli, long int, tolli, long long int, "li")
+DEF_STR_TO_INT(toi, int, tolli, long long int, "i")
+#undef DEF_STR_TO_INT
+#define tozu tolu
+#define tozi toli
+#define toju tollu
+#define toji tolli
+
+#define DEF_STR_TO_INT(FNAME, TYPE, PRI)\
+ static inline TYPE\
+ en##FNAME##_flag(int status, int flag, const char *s, TYPE min, TYPE max)\
+ {\
+ TYPE ret = 0;\
+ if (!FNAME(s, min, max, &ret))\
+ enprintf(status,\
+ "argument of -%c must be an integer in [%"PRI", %"PRI"]\n",\
+ flag, min, max);\
+ return ret;\
+ }\
+ \
+ static inline TYPE\
+ e##FNAME##_flag(int flag, const char *s, TYPE min, TYPE max)\
+ {\
+ return en##FNAME##_flag(1, flag, s, min, max);\
+ }\
+ \
+ static inline TYPE\
+ en##FNAME##_arg(int status, const char *name, const char *s, TYPE min, TYPE max)\
+ {\
+ TYPE ret = 0;\
+ if (!FNAME(s, min, max, &ret))\
+ enprintf(status,\
+ "%s must be an integer in [%"PRI", %"PRI"]\n",\
+ name, min, max);\
+ return ret;\
+ }\
+ \
+ static inline TYPE\
+ e##FNAME##_arg(const char *name, const char *s, TYPE min, TYPE max)\
+ {\
+ return en##FNAME##_arg(1, name, s, min, max);\
+ }
+DEF_STR_TO_INT(tollu, unsigned long long int, "llu")
+DEF_STR_TO_INT(tolu, unsigned long int, "lu")
+DEF_STR_TO_INT(tou, unsigned int, "u")
+DEF_STR_TO_INT(tolli, long long int, "lli")
+DEF_STR_TO_INT(toli, long int, "li")
+DEF_STR_TO_INT(toi, int, "i")
+#undef DEF_STR_TO_INT
+
+#define etozu_flag etolu_flag
+#define etozi_flag etoli_flag
+#define etoju_flag etollu_flag
+#define etoji_flag etolli_flag
+#define entozu_flag entolu_flag
+#define entozi_flag entoli_flag
+#define entoju_flag entollu_flag
+#define entoji_flag entolli_flag
+
+#define etozu_arg etolu_arg
+#define etozi_arg etoli_arg
+#define etoju_arg etollu_arg
+#define etoji_arg etolli_arg
+#define entozu_arg entolu_arg
+#define entozi_arg entoli_arg
+#define entoju_arg entollu_arg
+#define entoji_arg entolli_arg
+
+#define DEF_STR_TO_FLOAT(FNAME, TYPE, FUN)\
+ static inline int\
+ FNAME(const char *s, TYPE *out)\
+ {\
+ char *end;\
+ errno = 0;\
+ *out = FUN(s, &end);\
+ if (errno) {\
+ return -1;\
+ } else if (*end) {\
+ errno = EINVAL;\
+ return -1;\
+ }\
+ return 0;\
+ }\
+ \
+ static inline TYPE\
+ en##FNAME##_flag(int status, int flag, const char *s)\
+ {\
+ TYPE ret = 0;\
+ if (!FNAME(s, &ret))\
+ enprintf(status, "argument of -%c must be floating-point value\n", flag);\
+ return ret;\
+ }\
+ \
+ static inline TYPE\
+ e##FNAME##_flag(int flag, const char *s)\
+ {\
+ return en##FNAME##_flag(1, flag, s);\
+ }\
+ \
+ static inline TYPE\
+ en##FNAME##_arg(int status, const char *name, const char *s)\
+ {\
+ TYPE ret = 0;\
+ if (!FNAME(s, &ret))\
+ enprintf(status, "%s must be floating-point value\n", name);\
+ return ret;\
+ }\
+ \
+ static inline TYPE\
+ e##FNAME##_arg(const char *name, const char *s)\
+ {\
+ return en##FNAME##_arg(1, name, s);\
+ }
+DEF_STR_TO_FLOAT(tof, float, strtof)
+DEF_STR_TO_FLOAT(tolf, double, strtod)
+DEF_STR_TO_FLOAT(tollf, long double, strtold)
+#undef DEF_STR_TO_FLOAT
diff --git a/src/vu-arithm.c b/src/vu-arithm.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -9,15 +8,11 @@
#include <string.h>
#include <unistd.h>
+USAGE("right-hand-stream")
+
/* Because the syntax for a function returning a function pointer is disgusting. */
typedef void (*process_func)(struct stream *left, struct stream *right, size_t n);
-static void
-usage(void)
-{
- eprintf("usage: %s operation right-hand-stream\n", argv0);
-}
-
#define LIST_OPERATORS\
X(add, *lh += rh)\
X(sub, *lh -= rh)\
@@ -64,32 +59,20 @@ main(int argc, char *argv[])
{
struct stream left;
struct stream right;
- ssize_t r;
- size_t i, n;
+ size_t n;
process_func process = NULL;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 2)
- usage();
+ ENOFLAGS(argc != 2);
left.file = "<stdin>";
left.fd = STDIN_FILENO;
einit_stream(&left);
right.file = argv[1];
- right.fd = open(right.file, O_RDONLY);
- if (right.fd < 0)
- eprintf("open %s:", right.file);
+ right.fd = eopen(right.file, O_RDONLY);
einit_stream(&right);
- if (left.width != right.width || left.height != right.height)
- eprintf("videos do not have the same geometry\n");
- if (left.pixel_size != right.pixel_size)
- eprintf("videos use incompatible pixel formats\n");
+ echeck_compat(&left, &right);
if (!strcmp(left.pixfmt, "xyza"))
process = get_lf_process(argv[0]);
@@ -115,12 +98,7 @@ main(int argc, char *argv[])
process(&left, &right, n);
- for (i = 0; i < n; i += (size_t)r) {
- r = write(STDOUT_FILENO, left.buf + i, n - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
-
+ ewriteall(STDOUT_FILENO, left.buf, n, "<stdout>");
if ((n & 3) || left.ptr != right.ptr) {
memmove(left.buf, left.buf + n, left.ptr);
memmove(right.buf, right.buf + n, right.ptr);
@@ -130,11 +108,7 @@ main(int argc, char *argv[])
if (right.fd >= 0)
close(right.fd);
- for (i = 0; i < left.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, left.buf + i, left.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, left.buf, left.ptr, "<stdout>");
if (left.fd >= 0) {
for (;;) {
@@ -144,12 +118,7 @@ main(int argc, char *argv[])
left.fd = -1;
break;
}
-
- for (i = 0; i < left.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, left.buf + i, left.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, left.buf, left.ptr, "<stdout>");
}
}
diff --git a/src/vu-colour-srgb.c b/src/vu-colour-srgb.c
@@ -1,25 +1,18 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "util.h"
-static void
-usage(void)
-{
- eprintf("usage: %s [-d depth] [-l] red green blue\n", argv0);
-}
+USAGE("[-d depth] [-l] red green blue")
int
main(int argc, char *argv[])
{
unsigned long long int max;
double red, green, blue, X, Y, Z;
- int depth = 8;
- int linear = 0;
+ int depth = 8, linear = 0;
ARGBEGIN {
case 'd':
- if (toi(EARGF(usage()), 1, 64, &depth))
- eprintf("argument of -d must be an integer in [1, 64]\n");
+ depth = etoi_flag('d', EARG(), 1, 64);
break;
case 'l':
linear = 1;
@@ -31,18 +24,11 @@ main(int argc, char *argv[])
if (argc != 3)
usage();
- if (tolf(argv[0], &red))
- eprintf("the X value must be a floating-point value\n");
- if (tolf(argv[1], &green))
- eprintf("the Y value must be a floating-point value\n");
- if (tolf(argv[2], &blue))
- eprintf("the Z value must be a floating-point value\n");
-
- max = 1ULL << (depth - 1);
- max |= max - 1;
- red /= max;
- green /= max;
- blue /= max;
+ max = 1ULL << (depth - 1);
+ max |= max - 1;
+ red = etolf_arg("the red value", argv[0]) / max;
+ green = etolf_arg("the green value", argv[1]) / max;
+ blue = etolf_arg("the blue value", argv[2]) / max;
if (!linear) {
red = srgb_decode(red);
green = srgb_decode(green);
@@ -51,7 +37,7 @@ main(int argc, char *argv[])
srgb_to_ciexyz(red, green, blue, &X, &Y, &Z);
printf("%lf %lf %lf\n", X, Y, Z);
- efshut(stdout, "<stdout>");
+ efshut(stdout, "<stdout>");
return 0;
}
diff --git a/src/vu-concat.c b/src/vu-concat.c
@@ -1,53 +1,30 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
+#include <sys/mman.h>
#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s first-stream ... last-stream\n", argv0);
-}
+USAGE("[-o output-file] first-stream ... last-stream")
-int
-main(int argc, char *argv[])
+static void
+concat_to_stdout(int argc, char *argv[])
{
struct stream *streams;
- size_t ptr, frames = 0;
- ssize_t r;
+ size_t frames = 0;
int i;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc < 2)
- usage();
-
- streams = malloc((size_t)argc * sizeof(*streams));
- if (!streams)
- eprintf("malloc:");
+ streams = emalloc((size_t)argc * sizeof(*streams));
for (i = 0; i < argc; i++) {
streams[i].file = argv[i];
- streams[i].fd = open(streams[i].file, O_RDONLY);
- if (streams[i].fd < 0)
- eprintf("open %s:", streams[i].file);
+ streams[i].fd = eopen(streams[i].file, O_RDONLY);
einit_stream(streams + i);
-
- if (i) {
- if (streams[i].width != streams->width || streams[i].height != streams->height)
- eprintf("videos do not have the same geometry\n");
- if (strcmp(streams[i].pixfmt, streams->pixfmt))
- eprintf("videos use incompatible pixel formats\n");
- }
-
+ if (i)
+ echeck_compat(streams + i, streams);
if (streams[i].frames > SIZE_MAX - frames)
eprintf("resulting video is too long\n");
frames += streams[i].frames;
@@ -55,20 +32,79 @@ main(int argc, char *argv[])
streams->frames = frames;
fprint_stream_head(stdout, streams);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
- for (i = 0; i < argc; i++) {
- for (; eread_stream(streams + i, SIZE_MAX); streams[i].ptr = 0) {
- for (ptr = 0; ptr < streams[i].ptr; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, streams[i].buf + ptr, streams[i].ptr - ptr);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ for (; argc--; streams++) {
+ for (; eread_stream(streams, SIZE_MAX); streams->ptr = 0)
+ ewriteall(STDOUT_FILENO, streams->buf, streams->ptr, "<stdout>");
+ close(streams->fd);
+ }
+}
+
+static void
+concat_to_file(int argc, char *argv[], char *output_file)
+{
+ struct stream stream, refstream;
+ int first = 0;
+ int fd = eopen(output_file, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ char head[3 * sizeof(size_t) + 4 + sizeof(stream.pixfmt) + 6];
+ ssize_t headlen, size = 0;
+ char *data;
+
+ for (; argc--; argv++) {
+ stream.file = *argv;
+ stream.fd = eopen(stream.file, O_RDONLY);
+ einit_stream(&stream);
+
+ if (first) {
+ stream = refstream;
+ } else {
+ if (refstream.frames > SIZE_MAX - stream.frames)
+ eprintf("resulting video is too long\n");
+ refstream.frames += stream.frames;
+ echeck_compat(&stream, &refstream);
+ }
+
+ for (; eread_stream(&stream, SIZE_MAX); stream.ptr = 0) {
+ ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, "<stdout>");
+ size += stream.ptr;
}
- close(streams[i].fd);
+ close(stream.fd);
}
+ sprintf(head, "%zu %zu %zu %s\n%cuivf%zn",
+ stream.frames, stream.width, stream.height, stream.pixfmt, 0, &headlen);
+
+ ewriteall(STDOUT_FILENO, head, (size_t)headlen, "<stdout>");
+
+ data = mmap(0, size + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ memmove(data + headlen, data, size);
+ memcpy(data, head, (size_t)headlen);
+ munmap(data, size + (size_t)headlen);
+
+ close(fd);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *output_file = NULL;
+
+ ARGBEGIN {
+ case 'o':
+ output_file = EARG();
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc < 2)
+ usage();
+
+ if (output_file)
+ concat_to_file(argc, argv, output_file);
+ else
+ concat_to_stdout(argc, argv);
+
return 0;
}
diff --git a/src/vu-crop.c b/src/vu-crop.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,11 +7,7 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: [-t] width height left top %s\n", argv0);
-}
+USAGE("[-t] width height left top")
int
main(int argc, char *argv[])
@@ -20,7 +15,7 @@ main(int argc, char *argv[])
struct stream stream;
char *buf, *image, *p;
size_t width = 0, height = 0, left = 0, top = 0;
- size_t off, yoff, x, y, irown, orown, ptr, n, m;
+ size_t off, yoff = 0, x, y, irown, orown, ptr, n, m;
ssize_t r;
int tile = 0;
@@ -35,14 +30,10 @@ main(int argc, char *argv[])
if (argc != 4)
usage();
- if (tozu(argv[0], 1, SIZE_MAX, &width))
- eprintf("width be an integer in [1, %zu]\n", SIZE_MAX);
- if (tozu(argv[1], 1, SIZE_MAX, &height))
- eprintf("height be an integer in [1, %zu]\n", SIZE_MAX);
- if (tozu(argv[2], 0, SIZE_MAX, &left))
- eprintf("left position be an integer in [0, %zu]\n", SIZE_MAX);
- if (tozu(argv[3], 0, SIZE_MAX, &top))
- eprintf("top position be an integer in [0, %zu]\n", SIZE_MAX);
+ width = etozu_arg("the width", argv[0], 1, SIZE_MAX);
+ height = etozu_arg("the height", argv[1], 1, SIZE_MAX);
+ left = etozu_arg("the left position", argv[2], 0, SIZE_MAX);
+ top = etozu_arg("the top position", argv[3], 0, SIZE_MAX);
stream.file = "<stdin>";
stream.fd = STDIN_FILENO;
@@ -58,29 +49,21 @@ main(int argc, char *argv[])
stream.width = x;
stream.height = y;
}
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
- if (stream.width > SIZE_MAX / stream.pixel_size)
- eprintf("<stdin>: video frame is too large\n");
- n = irown = stream.width * stream.pixel_size;
- if (n > SIZE_MAX / stream.height)
- eprintf("<stdin>: video frame is too large\n");
- n *= stream.height;
- if (!(buf = malloc(n)))
- eprintf("malloc:");
+ echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file);
+ n = stream.height * (irown = stream.width * stream.pixel_size);
+ buf = emalloc(n);
orown = width * stream.pixel_size;
m = tile ? n : height * orown;
- if (!(image = malloc(m)))
- eprintf("malloc:");
+ image = emalloc(m);
left *= stream.pixel_size;
- if (tile) {
+ if (!tile) {
+ off = top * irown;
+ } else {
off = (orown - (left % orown)) % orown;
yoff = (height - (top % height)) % height;
- } else {
- off = top * irown;
}
memcpy(buf, stream.buf, ptr = stream.ptr);
for (;;) {
@@ -106,14 +89,9 @@ main(int argc, char *argv[])
for (x = 0; x < irown; x++, ptr++)
image[ptr++] = p[(x + off) % orown];
}
-
}
- for (ptr = 0; ptr < m; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, image + ptr, m - ptr);
- if (r < 0)
- eprintf("write <stdout>");
- }
+ ewriteall(STDOUT_FILENO, image, m, "<stdout>");
}
return 0;
diff --git a/src/vu-cut.c b/src/vu-cut.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -9,45 +8,31 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s start-point (end-point | 'end') file\n", argv0);
-}
+USAGE("start-point (end-point | 'end') file")
int
main(int argc, char *argv[])
{
struct stream stream;
- size_t frame_size, start = 0, end = 0, ptr, max, n, ptw;
+ size_t frame_size, start = 0, end = 0, ptr, max, n;
ssize_t r;
char buf[BUFSIZ];
int to_end = 0;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 3)
- usage();
+ ENOFLAGS(argc != 3);
- if (!strcmp(argv[0], "end")) {
+ if (!strcmp(argv[0], "end"))
eprintf("refusing to create video with zero frames\n");
- } else if (tozu(argv[0], 0, SIZE_MAX, &start)) {
- eprintf("the start point must be an integer in [0, %zu]\n", SIZE_MAX);
- }
+ else
+ start = etozu_arg("the start point", argv[1], 0, SIZE_MAX);
- if (!strcmp(argv[1], "end")) {
+ if (!strcmp(argv[1], "end"))
to_end = 1;
- } else if (tozu(argv[1], 0, SIZE_MAX, &end)) {
- eprintf("the end point must be an integer in [0, %zu]\n", SIZE_MAX);
- }
+ else
+ end = etozu_arg("the end point", argv[1], 0, SIZE_MAX);
stream.file = argv[2];
- stream.fd = open(stream.file, O_RDONLY);
- if (stream.fd < 0)
- eprintf("open %s:", stream.file);
+ stream.fd = eopen(stream.file, O_RDONLY);
einit_stream(&stream);
if (to_end)
end = stream.frames;
@@ -55,12 +40,9 @@ main(int argc, char *argv[])
eprintf("end point is after end of video\n");
stream.frames = end - start;
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
- if (stream.width > SIZE_MAX / stream.height)
- eprintf("%s: video is too large\n", stream.file);
- frame_size = stream.width * stream.height;
+ efflush(stdout, "<stdout>");
+ echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file);
+ frame_size = stream.width * stream.height * stream.pixel_size;
if (stream.frames > SSIZE_MAX / frame_size)
eprintf("%s: video is too large\n", stream.file);
@@ -68,7 +50,7 @@ main(int argc, char *argv[])
eprintf("%s\n", start > end ?
"start point is after end point" :
"refusing to create video with zero frames");
- end *= frame_size;
+ end *= frame_size;
start *= frame_size;
for (ptr = start; ptr < end;) {
@@ -80,11 +62,7 @@ main(int argc, char *argv[])
if (r == 0)
eprintf("%s: file is shorter than expected\n", stream.file);
ptr += n = (size_t)r;
- for (ptw = 0; ptw < n; ptw += (size_t)r) {
- r = write(STDOUT_FILENO, buf + ptw, n - ptw);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, buf, n, "<stdout>");
}
close(stream.fd);
diff --git a/src/vu-dissolve.c b/src/vu-dissolve.c
@@ -1,37 +1,35 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s [-r]\n", argv0);
-}
+USAGE("[-r]")
+
+static size_t fm;
+static double fmd;
static void
-process_xyza(struct stream *stream, size_t n, size_t f, size_t fm)
+process_xyza(struct stream *stream, size_t n, size_t f)
{
size_t i;
double a;
for (i = 0; i < n; i += stream->pixel_size) {
a = ((double *)(stream->buf + i))[3];
- a = a * (double)f / fm;
+ a = a * (double)f / fmd;
((double *)(stream->buf + i))[3] = a;
}
}
static void
-process_xyza_r(struct stream *stream, size_t n, size_t f, size_t fm)
+process_xyza_r(struct stream *stream, size_t n, size_t f)
{
size_t i;
double a;
for (i = 0; i < n; i += stream->pixel_size) {
a = ((double *)(stream->buf + i))[3];
- a = a * (double)(fm - f) / fm;
+ a = a * (double)(fm - f) / fmd;
((double *)(stream->buf + i))[3] = a;
}
}
@@ -41,10 +39,7 @@ main(int argc, char *argv[])
{
struct stream stream;
int reverse = 0;
- size_t f, h, w;
- size_t n, i, fm;
- ssize_t r;
- void (*process)(struct stream *stream, size_t n, size_t f, size_t fm) = NULL;
+ void (*process)(struct stream *stream, size_t n, size_t f) = NULL;
ARGBEGIN {
case 'r':
@@ -61,32 +56,15 @@ main(int argc, char *argv[])
stream.file = "<stdin>";
einit_stream(&stream);
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
if (!strcmp(stream.pixfmt, "xyza"))
process = reverse ? process_xyza_r : process_xyza;
else
eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
- fm = stream.frames - 1;
- for (f = 0; f < stream.frames; f++) {
- for (h = stream.height; h--;) {
- for (w = stream.width * stream.pixel_size; w; w -= n) {
- if (!eread_stream(&stream, w))
- eprintf("<stdin>: file is shorter than expected\n");
- n = stream.ptr - (stream.ptr % stream.pixel_size);
- process(&stream, n, f, fm);
- for (i = 0; i < n; i += (size_t)r) {
- r = write(STDOUT_FILENO, stream.buf + i, n - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
- memmove(stream.buf, stream.buf + n, stream.ptr -= n);
- }
- }
- }
+ fmd = fm = stream.frames - 1;
+ EACH_FRAME_SEGMENTED(&stream, process);
return 0;
}
diff --git a/src/vu-extend.c b/src/vu-extend.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,11 +7,7 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s [-l left] [-r right] [-a above] [-b below] [-t]\n", argv0);
-}
+USAGE("[-l left] [-r right] [-a above] [-b below] [-t]")
int
main(int argc, char *argv[])
@@ -27,20 +22,16 @@ main(int argc, char *argv[])
ARGBEGIN {
case 'l':
- if (tozu(EARGF(usage()), 0, SIZE_MAX, &left))
- eprintf("argument of -l must be an integer in [0, %zu]\n", SIZE_MAX);
+ left = etozu_flag('l', EARG(), 0, SIZE_MAX);
break;
case 'r':
- if (tozu(EARGF(usage()), 0, SIZE_MAX, &right))
- eprintf("argument of -r must be an integer in [0, %zu]\n", SIZE_MAX);
+ right = etozu_flag('r', EARG(), 0, SIZE_MAX);
break;
case 'a':
- if (tozu(EARGF(usage()), 0, SIZE_MAX, &top))
- eprintf("argument of -a must be an integer in [0, %zu]\n", SIZE_MAX);
+ top = etozu_flag('a', EARG(), 0, SIZE_MAX);
break;
case 'b':
- if (tozu(EARGF(usage()), 0, SIZE_MAX, &bottom))
- eprintf("argument of -b must be an integer in [0, %zu]\n", SIZE_MAX);
+ bottom = etozu_flag('b', EARG(), 0, SIZE_MAX);
break;
case 't':
tile = 1;
@@ -56,14 +47,9 @@ main(int argc, char *argv[])
stream.fd = STDIN_FILENO;
einit_stream(&stream);
- if (stream.width > SIZE_MAX / stream.pixel_size)
- eprintf("<stdin>: video frame is too large\n");
- n = stream.width * stream.pixel_size;
- if (n > SIZE_MAX / stream.height)
- eprintf("<stdin>: video frame is too large\n");
- n *= stream.height;
- if (!(buf = malloc(n)))
- eprintf("malloc:");
+ echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file);
+ n = stream.height * stream.width * stream.pixel_size;
+ buf = emalloc(n);
if (stream.width > SIZE_MAX - left)
eprintf("<stdout>: output video is too wide\n");
@@ -77,14 +63,9 @@ main(int argc, char *argv[])
if (imgh > SIZE_MAX - bottom)
eprintf("<stdout>: output video is too tall\n");
imgh += bottom;
- if (imgw > SIZE_MAX / stream.pixel_size)
- eprintf("<stdout>: output video frame is too large\n");
- m = imgw *= stream.pixel_size;
- if (m > SIZE_MAX / imgh)
- eprintf("<stdout>: output video frame is too large\n");
- m *= imgh;
- if (!(image = malloc(m)))
- eprintf("malloc:");
+ echeck_frame_size(imgw, imgh, stream.pixel_size, "output", "<stdout>");
+ m = imgh * (imgw *= stream.pixel_size);
+ image = emalloc(m);
if (!tile)
memset(image, 0, m);
@@ -92,9 +73,7 @@ main(int argc, char *argv[])
stream.width += left + right;
h = stream.height += top + bottom;
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
stream.width -= left + right;
stream.height -= top + bottom;
@@ -133,11 +112,7 @@ main(int argc, char *argv[])
memcpy(image + y * imgw, image + (((y + yoff) % stream.height) + top) * imgw, imgw);
}
- for (ptr = 0; ptr < m; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, image + ptr, m - ptr);
- if (r < 0)
- eprintf("write <stdout>");
- }
+ ewriteall(STDOUT_FILENO, image, m, "<stdout>");
}
return 0;
diff --git a/src/vu-flip.c b/src/vu-flip.c
@@ -1,81 +1,36 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
-#include <fcntl.h>
-#include <inttypes.h>
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s\n", argv0);
-}
+USAGE("")
int
main(int argc, char *argv[])
{
struct stream stream;
- char *buf, *row;
- size_t ptr, n, i, j, hm, row_size;
- ssize_t r;
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
+ size_t n, ptr, row_size;
+ char *buf;
- if (argc)
- usage();
+ ENOFLAGS(argc);
stream.file = "<stdin>";
stream.fd = STDIN_FILENO;
einit_stream(&stream);
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
- if (stream.width > SIZE_MAX / stream.pixel_size)
- eprintf("<stdin>: video is too wide\n");
- row_size = stream.width * stream.pixel_size;
- if (!(row = malloc(row_size)))
- eprintf("malloc:");
- if (row_size > SIZE_MAX / stream.height)
- eprintf("<stdin>: video frame is too large\n");
- n = row_size * stream.height;
- if (!(buf = malloc(n)))
- eprintf("malloc:");
+ echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file);
+ n = stream.height * (row_size = stream.width * stream.pixel_size);
+ buf = emalloc(n);
- hm = stream.height - 1;
- memcpy(buf, stream.buf, ptr = stream.ptr);
- for (;;) {
- for (; ptr < n; ptr += (size_t)r) {
- r = read(stream.fd, buf + ptr, n - ptr);
- if (r < 0) {
- eprintf("read %s:", stream.file);
- } else if (r == 0) {
- if (!ptr)
- break;
- eprintf("%s: incomplete frame", stream.file);
- }
- }
- if (!ptr)
- break;
- for (i = 0; i < stream.height >> 1; i++) {
- j = hm - i;
- memcpy(row, buf + i * row_size, row_size);
- memcpy(buf + i * row_size, buf + j * row_size, row_size);
- memcpy(buf + j * row_size, row, row_size);
- }
- for (ptr = 0; ptr < n; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, buf + ptr, n - ptr);
- if (r < 0)
- eprintf("write <stdout>");
- }
- }
+ memcpy(buf, stream.buf, stream.ptr);
+ while (eread_frame(&stream, buf, n))
+ for (ptr = n; ptr;)
+ ewriteall(STDOUT_FILENO, buf + (ptr -= row_size), row_size, "<stdout>");
+ free(buf);
return 0;
}
diff --git a/src/vu-flop.c b/src/vu-flop.c
@@ -1,79 +1,44 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
-#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s\n", argv0);
-}
+USAGE("")
int
main(int argc, char *argv[])
{
struct stream stream;
- char *buf, t1, t2;
- size_t ptr, n, i, j, k, wm;
- ssize_t r;
+ char *buf, *image;
+ size_t i, j, n, m;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc)
- usage();
+ ENOFLAGS(argc);
stream.file = "<stdin>";
stream.fd = STDIN_FILENO;
einit_stream(&stream);
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
if (stream.width > SIZE_MAX / stream.pixel_size)
- eprintf("<stdin>: video is too wide\n");
+ eprintf("<stdin>: video frame is too wide\n");
n = stream.width * stream.pixel_size;
- if (!(buf = malloc(n)))
- eprintf("malloc:");
-
- wm = stream.width - 1;
- memcpy(buf, stream.buf, ptr = stream.ptr);
- for (;;) {
- for (; ptr < n; ptr += (size_t)r) {
- r = read(stream.fd, buf + ptr, n - ptr);
- if (r < 0) {
- eprintf("read %s:", stream.file);
- } else if (r == 0) {
- if (!ptr)
- break;
- eprintf("%s: incomplete frame", stream.file);
- }
- }
- if (!ptr)
- break;
- for (i = 0; i < stream.pixel_size; i++) {
- for (j = 0; j < stream.width >> 1; j++) {
- k = wm - j;
- t1 = buf[j * stream.pixel_size + i];
- t2 = buf[k * stream.pixel_size + i];
- buf[j * stream.pixel_size + i] = t2;
- buf[k * stream.pixel_size + i] = t1;
- }
- }
- for (ptr = 0; ptr < n; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, buf + ptr, n - ptr);
- if (r < 0)
- eprintf("write <stdout>");
- }
+ buf = emalloc(n);
+ image = emalloc(n);
+
+ m = n - stream.pixel_size;
+ memcpy(buf, stream.buf, stream.ptr);
+ while (eread_row(&stream, buf, n)) {
+ for (i = 0; i < stream.pixel_size; i++)
+ for (j = 0; j < n; j += stream.pixel_size)
+ image[m - j + i] = buf[i + j];
+ ewriteall(STDOUT_FILENO, image, n, "<stdout>");
}
+ free(buf);
+ free(image);
return 0;
}
diff --git a/src/vu-from-image.c b/src/vu-from-image.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "util.h"
#include <arpa/inet.h>
@@ -8,6 +7,8 @@
#include <string.h>
#include <unistd.h>
+USAGE("[-h] [-f | -p]")
+
static double
get_value(void *buffer)
{
@@ -25,21 +26,15 @@ get_value(void *buffer)
return ret;
}
-static void
-usage(void)
-{
- eprintf("usage: [-h] [-f | -p] %s\n", argv0);
-}
-
int
main(int argc, char *argv[])
{
int pipe_rw[2];
int i, old_fd;
- pid_t pid;
+ pid_t pid = 0;
int status;
char buf[8096];
- size_t ptr, ptw, n;
+ size_t ptr, n;
char *p;
ssize_t r;
double red, green, blue, pixel[4];
@@ -164,10 +159,8 @@ header_done:
eprintf("%s\n", conv_fail_msg);
if (!headless) {
- printf("%s %s xyza\n%cuivf", width, height, 0);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ printf("1 %s %s xyza\n%cuivf", width, height, 0);
+ efflush(stdout, "<stdout>");
}
for (;;) {
@@ -178,12 +171,7 @@ header_done:
pixel[3] = get_value(buf + ptr + 12);
srgb_to_ciexyz(red, green, blue, pixel + 0, pixel + 1, pixel + 2);
-
- for (ptw = 0; ptw < sizeof(pixel); ptw += (size_t)r) {
- r = write(STDOUT_FILENO, (char *)pixel + ptw, sizeof(pixel) - ptw);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, pixel, sizeof(pixel), "<stdout>");
}
r = read(pipe_rw[0], buf, sizeof(buf));
if (r < 0)
diff --git a/src/vu-invert-luma.c b/src/vu-invert-luma.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,11 +7,7 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s [-i] mask-stream\n", argv0);
-}
+USAGE("[-i] mask-stream")
static void
process_xyza(struct stream *colour, struct stream *mask, size_t n)
@@ -46,10 +41,8 @@ int
main(int argc, char *argv[])
{
int invert = 0;
- struct stream colour;
- struct stream mask;
- ssize_t r;
- size_t i, n;
+ struct stream colour, mask;
+ size_t n;
void (*process)(struct stream *colour, struct stream *mask, size_t n) = NULL;
ARGBEGIN {
@@ -68,15 +61,10 @@ main(int argc, char *argv[])
einit_stream(&colour);
mask.file = argv[0];
- mask.fd = open(mask.file, O_RDONLY);
- if (mask.fd < 0)
- eprintf("open %s:", mask.file);
+ mask.fd = eopen(mask.file, O_RDONLY);
einit_stream(&mask);
- if (colour.width != mask.width || colour.height != mask.height)
- eprintf("videos do not have the same geometry\n");
- if (colour.pixel_size != mask.pixel_size)
- eprintf("videos use incompatible pixel formats\n");
+ echeck_compat(&colour, &mask);
if (!strcmp(colour.pixfmt, "xyza"))
process = invert ? process_xyza_i : process_xyza;
@@ -102,12 +90,7 @@ main(int argc, char *argv[])
process(&colour, &mask, n);
- for (i = 0; i < n; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, n - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
-
+ ewriteall(STDOUT_FILENO, colour.buf, n, "<stdout>");
if ((n & 3) || colour.ptr != mask.ptr) {
memmove(colour.buf, colour.buf + n, colour.ptr);
memmove(mask.buf, mask.buf + n, mask.ptr);
@@ -117,11 +100,7 @@ main(int argc, char *argv[])
if (mask.fd >= 0)
close(mask.fd);
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
if (colour.fd >= 0) {
for (;;) {
@@ -131,12 +110,7 @@ main(int argc, char *argv[])
colour.fd = -1;
break;
}
-
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
}
}
diff --git a/src/vu-next-frame.c b/src/vu-next-frame.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -7,40 +6,28 @@
#include <string.h>
#include <unistd.h>
+#undef eprintf
#define eprintf(...) enprintf(2, __VA_ARGS__)
-static void
-usage(void)
-{
- eprintf("usage: %s width height pixel-format ...\n", argv0);
-}
+USAGE("width height pixel-format ...")
int
main(int argc, char *argv[])
{
struct stream stream;
- size_t ptr, n, w;
- ssize_t r;
+ size_t n, w;
int i, anything = 0;
char *p;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc < 3)
- usage();
+ ENOFLAGS(argc < 3);
stream.frames = 1;
stream.fd = STDIN_FILENO;
stream.file = "<stdin>";
stream.pixfmt[0] = '\0';
- if (tozu(argv[0], 1, SIZE_MAX, &stream.width))
- eprintf("the width must be an integer in [1, %zu]\n", SIZE_MAX);
- if (tozu(argv[1], 1, SIZE_MAX, &stream.height))
- eprintf("the height must be an integer in [1, %zu]\n", SIZE_MAX);
+ stream.width = etozu_arg("the width", argv[0], 1, SIZE_MAX);
+ stream.height = etozu_arg("the height", argv[1], 1, SIZE_MAX);
argv += 2, argc -= 2;
n = (size_t)argc - 1;
@@ -57,28 +44,22 @@ main(int argc, char *argv[])
eset_pixel_size(&stream);
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
+ w = stream.width * stream.pixel_size;
while (stream.height) {
stream.height--;
- for (w = stream.width * stream.pixel_size; w; w -= n) {
+ for (n = w; n; n -= stream.ptr) {
stream.ptr = 0;
- n = eread_stream(&stream, w);
- if (n == 0)
+ if (!eread_stream(&stream, n))
goto done;
anything = 1;
- for (ptr = 0; ptr < stream.ptr; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, stream.buf + ptr, stream.ptr - ptr);
- if (r < 0)
- eprintf("write <stdin>:");
- }
+ ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, "<stdout>");
}
}
done:
- if (stream.height || w)
+ if (stream.height || n)
eprintf("incomplete frame\n");
return !anything;
diff --git a/src/vu-read-head.c b/src/vu-read-head.c
@@ -1,34 +1,22 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
#include <ctype.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s\n", argv0);
-}
+USAGE("")
int
main(int argc, char *argv[])
{
char buf[2 + 3 * sizeof(size_t) + sizeof(((struct stream *)0)->pixfmt)];
char magic[] = {'\0', 'u', 'i', 'v', 'f'};
- char b;
- char *p;
+ char b, *p;
size_t i, ptr;
ssize_t r;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (!argc)
- usage();
+ ENOFLAGS(!argc);
for (ptr = 0; ptr < sizeof(buf);) {
r = read(STDIN_FILENO, buf + ptr, 1);
@@ -47,11 +35,11 @@ main(int argc, char *argv[])
r = read(STDIN_FILENO, &b, 1);
if (r < 0)
eprintf("read <stdin>:");
- if (!r || b != magic[i])
+ if (r == 0 || b != magic[i])
goto bad_format;
}
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
if (!isdigit(*p))
goto bad_format;
while (isdigit(*p)) p++;
@@ -66,13 +54,10 @@ main(int argc, char *argv[])
if (p[-1] == ' ' || p[0] != '\n')
goto bad_format;
- for (i = 0; i < ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, buf + i, ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, buf, ptr, "<stdout>");
return 0;
bad_format:
eprintf("<stdin>: file format not supported\n");
+ return 0;
}
diff --git a/src/vu-repeat.c b/src/vu-repeat.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -9,59 +8,40 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s (count | 'inf') file\n", argv0);
-}
+USAGE("(count | 'inf') file")
int
main(int argc, char *argv[])
{
struct stream stream;
- size_t count = 0, ptr, n, ptw;
+ size_t count = 0, ptr, n;
ssize_t r;
char buf[BUFSIZ];
int inf = 0;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
+ ENOFLAGS(argc != 2);
- if (argc != 2)
- usage();
-
- if (!strcmp(argv[0], "inf")) {
+ if (!strcmp(argv[0], "inf"))
inf = 1;
- } else if (tozu(argv[0], 0, SIZE_MAX, &count)) {
- eprintf("the count must be an integer in [0, %zu]\n", SIZE_MAX);
- }
+ else
+ count = etozu_arg("the count", argv[0], 0, SIZE_MAX);
if (inf)
einf_check_fd(STDOUT_FILENO, "<stdout>");
stream.file = argv[1];
- stream.fd = open(stream.file, O_RDONLY);
- if (stream.fd < 0)
- eprintf("open %s:", stream.file);
+ stream.fd = eopen(stream.file, O_RDONLY);
einit_stream(&stream);
if (count > SIZE_MAX / stream.frames)
- eprintf("%s: video too long\n", stream.file);
+ eprintf("%s: video is too long\n", stream.file);
stream.frames *= count;
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
while (inf || count--) {
posix_fadvise(stream.fd, 0, 0, POSIX_FADV_SEQUENTIAL);
- for (ptw = 0; ptw < stream.ptr;) {
- r = write(STDOUT_FILENO, stream.buf + ptw, stream.ptr - ptw);
- if (r < 0)
- goto writeerr;
- ptw += (size_t)r;
- }
+ if (writeall(STDOUT_FILENO, stream.buf, stream.ptr))
+ goto writeerr;
for (ptr = 0;;) {
r = pread(stream.fd, buf, sizeof(buf), ptr);
if (r < 0)
@@ -69,12 +49,8 @@ main(int argc, char *argv[])
else if (r == 0)
break;
ptr += n = (size_t)r;
- for (ptw = 0; ptw < n;) {
- r = write(STDOUT_FILENO, buf + ptw, n - ptw);
- if (r < 0)
- goto writeerr;
- ptw += (size_t)r;
- }
+ if (writeall(STDOUT_FILENO, buf, n))
+ goto writeerr;
}
}
diff --git a/src/vu-reverse.c b/src/vu-reverse.c
@@ -1,47 +1,29 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
-#include <fcntl.h>
#include <limits.h>
-#include <stdint.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s file\n", argv0);
-}
+USAGE("file")
int
main(int argc, char *argv[])
{
struct stream stream;
- size_t frame_size, ptr, end, n, ptw;
+ size_t frame_size, ptr, end, n;
ssize_t r;
char buf[BUFSIZ];
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 1)
- usage();
+ ENOFLAGS(argc != 1);
stream.file = argv[0];
- stream.fd = open(stream.file, O_RDONLY);
- if (stream.fd < 0)
- eprintf("open %s:", stream.file);
+ stream.fd = eopen(stream.file, O_RDONLY);
einit_stream(&stream);
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
- if (stream.width > SIZE_MAX / stream.height)
- eprintf("%s: video is too large\n", stream.file);
- frame_size = stream.width * stream.height;
+ efflush(stdout, "<stdout>");
+ echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file);
+ frame_size = stream.width * stream.height * stream.pixel_size;
if (stream.frames > SSIZE_MAX / frame_size)
eprintf("%s: video is too large\n", stream.file);
@@ -56,12 +38,7 @@ main(int argc, char *argv[])
else if (r == 0)
eprintf("%s: file is shorter than expected\n", stream.file);
ptr += n = (size_t)r;
- for (ptw = 0; ptw < n;) {
- r = write(STDOUT_FILENO, buf + ptw, n - ptw);
- if (r < 0)
- eprintf("write <stdout>:");
- ptw += (size_t)r;
- }
+ ewriteall(STDOUT_FILENO, buf, n, "<stdout>");
}
}
diff --git a/src/vu-set-alpha.c b/src/vu-set-alpha.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,11 +7,7 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s [-i] alpha-stream\n", argv0);
-}
+USAGE("[-i] alpha-stream")
static void
process_xyza(struct stream *colour, struct stream *alpha, size_t n)
@@ -42,10 +37,8 @@ int
main(int argc, char *argv[])
{
int invert = 0;
- struct stream colour;
- struct stream alpha;
- ssize_t r;
- size_t i, n;
+ struct stream colour, alpha;
+ size_t n;
void (*process)(struct stream *colour, struct stream *alpha, size_t n) = NULL;
ARGBEGIN {
@@ -64,15 +57,10 @@ main(int argc, char *argv[])
einit_stream(&colour);
alpha.file = argv[0];
- alpha.fd = open(alpha.file, O_RDONLY);
- if (alpha.fd < 0)
- eprintf("open %s:", alpha.file);
+ alpha.fd = eopen(alpha.file, O_RDONLY);
einit_stream(&alpha);
- if (colour.width != alpha.width || colour.height != alpha.height)
- eprintf("videos do not have the same geometry\n");
- if (colour.pixel_size != alpha.pixel_size)
- eprintf("videos use incompatible pixel formats\n");
+ echeck_compat(&colour, &alpha);
if (!strcmp(colour.pixfmt, "xyza"))
process = invert ? process_xyza_i : process_xyza;
@@ -98,12 +86,7 @@ main(int argc, char *argv[])
process(&colour, &alpha, n);
- for (i = 0; i < n; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, n - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
-
+ ewriteall(STDOUT_FILENO, colour.buf, n, "<stdout>");
if ((n & 3) || colour.ptr != alpha.ptr) {
memmove(colour.buf, colour.buf + n, colour.ptr);
memmove(alpha.buf, alpha.buf + n, alpha.ptr);
@@ -113,11 +96,7 @@ main(int argc, char *argv[])
if (alpha.fd >= 0)
close(alpha.fd);
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
if (colour.fd >= 0) {
for (;;) {
@@ -127,12 +106,7 @@ main(int argc, char *argv[])
colour.fd = -1;
break;
}
-
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
}
}
diff --git a/src/vu-set-luma.c b/src/vu-set-luma.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,11 +7,7 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s luma-stream\n", argv0);
-}
+USAGE("luma-stream")
static void
process_xyza(struct stream *colour, struct stream *luma, size_t n)
@@ -29,34 +24,21 @@ process_xyza(struct stream *colour, struct stream *luma, size_t n)
int
main(int argc, char *argv[])
{
- struct stream colour;
- struct stream luma;
- ssize_t r;
- size_t i, n;
+ struct stream colour, luma;
+ size_t n;
void (*process)(struct stream *colour, struct stream *luma, size_t n);
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc != 1)
- usage();
+ ENOFLAGS(argc != 1);
colour.file = "<stdin>";
colour.fd = STDIN_FILENO;
einit_stream(&colour);
luma.file = argv[0];
- luma.fd = open(luma.file, O_RDONLY);
- if (luma.fd < 0)
- eprintf("open %s:", luma.file);
+ luma.fd = eopen(luma.file, O_RDONLY);
einit_stream(&luma);
- if (colour.width != luma.width || colour.height != luma.height)
- eprintf("videos do not have the same geometry\n");
- if (colour.pixel_size != luma.pixel_size)
- eprintf("videos use incompatible pixel formats\n");
+ echeck_compat(&colour, &luma);
if (!strcmp(colour.pixfmt, "xyza"))
process = process_xyza;
@@ -82,12 +64,7 @@ main(int argc, char *argv[])
process(&colour, &luma, n);
- for (i = 0; i < n; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, n - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
-
+ ewriteall(STDOUT_FILENO, colour.buf, n, "<stdout>");
if ((n & 3) || colour.ptr != luma.ptr) {
memmove(colour.buf, colour.buf + n, colour.ptr);
memmove(luma.buf, luma.buf + n, luma.ptr);
@@ -97,11 +74,7 @@ main(int argc, char *argv[])
if (luma.fd >= 0)
close(luma.fd);
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
if (colour.fd >= 0) {
for (;;) {
@@ -111,12 +84,7 @@ main(int argc, char *argv[])
colour.fd = -1;
break;
}
-
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
}
}
diff --git a/src/vu-set-saturation.c b/src/vu-set-saturation.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,11 +7,7 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s [-w] saturation-stream\n", argv0);
-}
+USAGE("[-w] saturation-stream")
static void
process_xyza(struct stream *colour, struct stream *satur, size_t n)
@@ -51,11 +46,9 @@ process_xyza_w(struct stream *colour, struct stream *satur, size_t n)
int
main(int argc, char *argv[])
{
- struct stream colour;
- struct stream satur;
+ struct stream colour, satur;
int whitepoint = 0;
- ssize_t r;
- size_t i, n;
+ size_t n;
void (*process)(struct stream *colour, struct stream *satur, size_t n) = NULL;
ARGBEGIN {
@@ -74,15 +67,10 @@ main(int argc, char *argv[])
einit_stream(&colour);
satur.file = argv[0];
- satur.fd = open(satur.file, O_RDONLY);
- if (satur.fd < 0)
- eprintf("open %s:", satur.file);
+ satur.fd = eopen(satur.file, O_RDONLY);
einit_stream(&satur);
- if (colour.width != satur.width || colour.height != satur.height)
- eprintf("videos do not have the same geometry\n");
- if (colour.pixel_size != satur.pixel_size)
- eprintf("videos use incompatible pixel formats\n");
+ echeck_compat(&colour, &satur);
if (!strcmp(colour.pixfmt, "xyza"))
process = whitepoint ? process_xyza_w : process_xyza;
@@ -108,12 +96,7 @@ main(int argc, char *argv[])
process(&colour, &satur, n);
- for (i = 0; i < n; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, n - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
-
+ ewriteall(STDOUT_FILENO, colour.buf, n, "<stdout>");
if ((n & 3) || colour.ptr != satur.ptr) {
memmove(colour.buf, colour.buf + n, colour.ptr);
memmove(satur.buf, satur.buf + n, satur.ptr);
@@ -123,11 +106,7 @@ main(int argc, char *argv[])
if (satur.fd >= 0)
close(satur.fd);
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
if (colour.fd >= 0) {
for (;;) {
@@ -137,12 +116,7 @@ main(int argc, char *argv[])
colour.fd = -1;
break;
}
-
- for (i = 0; i < colour.ptr; i += (size_t)r) {
- r = write(STDOUT_FILENO, colour.buf + i, colour.ptr - i);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, colour.buf, colour.ptr, "<stdout>");
}
}
diff --git a/src/vu-single-colour.c b/src/vu-single-colour.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -7,13 +6,9 @@
#include <string.h>
#include <unistd.h>
-typedef double pixel_t[4];
+USAGE("[-f frames | -f 'inf'] -w width -h height (X Y Z | Y) [alpha]")
-static void
-usage(void)
-{
- eprintf("usage: %s [-f frames | -f 'inf'] -w width -h height (X Y Z | Y) [alpha]\n", argv0);
-}
+typedef double pixel_t[4];
int
main(int argc, char *argv[])
@@ -32,19 +27,17 @@ main(int argc, char *argv[])
ARGBEGIN {
case 'f':
- arg = EARGF(usage());
+ arg = EARG();
if (!strcmp(arg, "inf"))
inf = 1, stream.frames = 0;
- else if (tozu(arg, 1, SIZE_MAX, &stream.frames))
- eprintf("argument of -f must be an integer in [1, %zu] or 'inf'\n", SIZE_MAX);
+ else
+ stream.frames = etozu_flag('f', arg, 1, SIZE_MAX);
break;
case 'w':
- if (tozu(EARGF(usage()), 1, SIZE_MAX, &stream.width))
- eprintf("argument of -w must be an integer in [1, %zu]\n", SIZE_MAX);
+ stream.width = etozu_flag('w', EARG(), 1, SIZE_MAX);
break;
case 'h':
- if (tozu(EARGF(usage()), 1, SIZE_MAX, &stream.height))
- eprintf("argument of -h must be an integer in [1, %zu]\n", SIZE_MAX);
+ stream.height = etozu_flag('h', EARG(), 1, SIZE_MAX);
break;
default:
usage();
@@ -56,27 +49,21 @@ main(int argc, char *argv[])
if (argc < 3) {
X = D65_XYY_X / D65_XYY_Y;
Z = 1 / D65_XYY_Y - 1 - X;
- if (tolf(argv[1], &Y))
- eprintf("the Y value must be a floating-point value\n");
+ Y = etolf_arg("the Y value", argv[1]);
} else {
- if (tolf(argv[0], &X))
- eprintf("the X value must be a floating-point value\n");
- if (tolf(argv[1], &Y))
- eprintf("the Y value must be a floating-point value\n");
- if (tolf(argv[2], &Z))
- eprintf("the Z value must be a floating-point value\n");
+ X = etolf_arg("the X value", argv[0]);
+ Y = etolf_arg("the Y value", argv[1]);
+ Z = etolf_arg("the Z value", argv[2]);
}
- if (!(argc & 1) && tolf(argv[argc - 1], &alpha))
- eprintf("the alpha value must be a floating-point value\n");
+ if (~argc & 1)
+ alpha = etolf_arg("the alpha value", argv[argc - 1]);
if (inf)
einf_check_fd(STDOUT_FILENO, "<stdout>");
strcpy(stream.pixfmt, "xyza");
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
for (x = 0; x < ELEMENTSOF(buf); x++) {
buf[x][0] = X;
diff --git a/src/vu-split.c b/src/vu-split.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -10,11 +9,7 @@
#include <string.h>
#include <unistd.h>
-static void
-usage(void)
-{
- eprintf("usage: %s (file end-point) ...\n", argv0);
-}
+USAGE("(file (end-point | 'end')) ...")
int
main(int argc, char *argv[])
@@ -25,20 +20,13 @@ main(int argc, char *argv[])
int fd;
ssize_t r;
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (argc < 2 || argc % 2)
- usage();
+ ENOFLAGS(argc < 2 || argc % 2);
stream.file = "<stdin>";
stream.fd = STDIN_FILENO;
einit_stream(&stream);
- if (stream.width > SIZE_MAX / stream.height)
- eprintf("%s: video is too large\n", stream.file);
- frame_size = stream.width * stream.height;
+ echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file);
+ frame_size = stream.width * stream.height * stream.pixel_size;
if (stream.frames > SSIZE_MAX / frame_size)
eprintf("%s: video is too large\n", stream.file);
@@ -58,16 +46,12 @@ main(int argc, char *argv[])
ptr = 0;
for (i = 0; i < parts; i++) {
- fd = open(argv[i * 2], O_WRONLY);
- if (fd < 0)
- eprintf("open %s:", argv[i * 2]);
+ fd = eopen(argv[i * 2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
fp = fdopen(fd, "wb");
stream.frames = ends[i] - (i ? ends[i - 1] : 0);
fprint_stream_head(fp, &stream);
- fflush(fp);
- if (ferror(fp))
- eprintf("%s:", argv[i * 2]);
+ efflush(fp, argv[i * 2]);
for (end = ends[i] * frame_size; ptr < end; ptr += n) {
for (ptw = ptr; stream.ptr && ptw < end;) {
diff --git a/src/vu-stack.c b/src/vu-stack.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,6 +7,8 @@
#include <string.h>
#include <unistd.h>
+USAGE("[-b] bottom-stream ... top-stream")
+
static void
process_xyza(struct stream *streams, size_t n_streams, size_t n)
{
@@ -65,12 +66,6 @@ process_xyza_b(struct stream *streams, size_t n_streams, size_t n)
}
}
-static void
-usage(void)
-{
- eprintf("usage: %s [-b] bottom-stream ... top-stream\n", argv0);
-}
-
int
main(int argc, char *argv[])
{
@@ -78,7 +73,6 @@ main(int argc, char *argv[])
size_t n_streams;
int blend = 0;
size_t i, j, n;
- ssize_t r;
size_t closed;
void (*process)(struct stream *streams, size_t n_streams, size_t n) = NULL;
@@ -94,21 +88,13 @@ main(int argc, char *argv[])
usage();
n_streams = (size_t)argc;
- streams = calloc(n_streams, sizeof(*streams));
- if (!streams)
- eprintf("calloc:");
+ streams = ecalloc(n_streams, sizeof(*streams));
for (i = 0; i < n_streams; i++) {
streams[i].file = argv[i];
- streams[i].fd = open(streams[i].file, O_RDONLY);
- if (streams[i].fd < 0)
- eprintf("open %s:", streams[i].file);
- if (i) {
- if (streams[i].width != streams->width || streams[i].height != streams->height)
- eprintf("videos do not have the same geometry\n");
- if (strcmp(streams[i].pixfmt, streams->pixfmt))
- eprintf("videos use incompatible pixel formats\n");
- }
+ streams[i].fd = eopen(streams[i].file, O_RDONLY);
+ if (i)
+ echeck_compat(streams + i, streams);
}
if (!strcmp(streams->pixfmt, "xyza"))
@@ -129,12 +115,8 @@ main(int argc, char *argv[])
n -= n % streams->pixel_size;
process(streams, n_streams, n);
- for (j = 0; j < n;) {
- r = write(STDOUT_FILENO, streams->buf + j, n - j);
- if (r < 0)
- eprintf("write <stdout>:");
- j += (size_t)r;
- }
+
+ ewriteall(STDOUT_FILENO, streams->buf, n, "<stdout>");
closed = SIZE_MAX;
for (i = 0; i < n_streams; i++) {
diff --git a/src/vu-to-image.c b/src/vu-to-image.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -10,24 +9,18 @@
#include <string.h>
#include <unistd.h>
+USAGE("[-d depth | -f]")
+
static int luma_warning_triggered = 0;
static int gamut_warning_triggered = 0;
static int alpha_warning_triggered = 0;
static void
-usage(void)
-{
- eprintf("usage: %s [-d depth | -f]\n", argv0);
-}
-
-static void
write_pixel(double R, double G, double B, double A, int bytes, unsigned long long int max)
{
unsigned long long int colours[4];
unsigned char buf[4 * 8];
int i, j, k, bm = bytes - 1;
- size_t ptr, n;
- ssize_t r;
if (R < 0 || G < 0 || B < 0 || R > 1 || G > 1 || B > 1) {
if (gamut_warning_triggered) {
@@ -60,12 +53,7 @@ write_pixel(double R, double G, double B, double A, int bytes, unsigned long lon
}
}
- n = (size_t)bytes * 4;
- for (ptr = 0; ptr < n; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, buf + ptr, n - ptr);
- if (r < 0)
- eprintf("write <stdout>:");
- }
+ ewriteall(STDOUT_FILENO, buf, (size_t)bytes * 4, "<stdout>");
}
static void
@@ -103,8 +91,7 @@ main(int argc, char *argv[])
ARGBEGIN {
case 'd':
- if (toi(EARGF(usage()), 1, 64, &depth))
- eprintf("argument of -d must be an integer in [1, 64]\n");
+ depth = etoi_flag('d', EARG(), 1, 64);
break;
case 'f':
farbfeld = 1;
@@ -151,18 +138,13 @@ main(int argc, char *argv[])
"TUPLTYPE RGB_ALPHA\n"
"ENDHDR\n", stream.width, stream.height, max);
}
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
+ efflush(stdout, "<stdout>");
- for (;;) {
- n = stream.ptr;
- n -= n % stream.pixel_size;
+ do {
+ n = stream.ptr - (stream.ptr % stream.pixel_size);
process(&stream, n, bytes, max);
memmove(stream.buf, stream.buf + n, stream.ptr -= n);
- if (!eread_stream(&stream, SIZE_MAX))
- break;
- }
+ } while (eread_stream(&stream, SIZE_MAX));
return 0;
}
diff --git a/src/vu-transpose.c b/src/vu-transpose.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "stream.h"
#include "util.h"
@@ -8,79 +7,39 @@
#include <string.h>
#include <unistd.h>
-static void
-transpose(const struct stream *stream, const char *restrict buf, char *restrict image)
-{
- size_t x, y, i, b = 0, h, w;
- w = stream->width * (h = stream->height * stream->pixel_size);
- for (y = 0; y < h; y += stream->pixel_size)
- for (x = 0; x < w; x += h)
- for (i = 0; i < stream->pixel_size; i++)
- image[x + y + i] = buf[b++];
-}
-
-static void
-usage(void)
-{
- eprintf("usage: %s\n", argv0);
-}
+USAGE("")
int
main(int argc, char *argv[])
{
struct stream stream;
char *buf, *image;
- size_t ptr, n;
- ssize_t r;
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
+ size_t n, imgw, imgh, x, y, i, b;
- if (argc)
- usage();
+ ENOFLAGS(argc);
stream.file = "<stdin>";
stream.fd = STDIN_FILENO;
einit_stream(&stream);
fprint_stream_head(stdout, &stream);
- fflush(stdout);
- if (ferror(stdout))
- eprintf("<stdout>:");
-
- if (stream.width > SIZE_MAX / stream.pixel_size)
- eprintf("<stdin>: video frame is too large\n");
- n = stream.width * stream.pixel_size;
- if (n > SIZE_MAX / stream.height)
- eprintf("<stdin>: video frame is too large\n");
- n *= stream.height;
- if (!(buf = malloc(n)))
- eprintf("malloc:");
- if (!(image = malloc(n)))
- eprintf("malloc:");
-
- memcpy(buf, stream.buf, ptr = stream.ptr);
- for (;;) {
- for (; ptr < n; ptr += (size_t)r) {
- r = read(stream.fd, buf + ptr, n - ptr);
- if (r < 0) {
- eprintf("read %s:", stream.file);
- } else if (r == 0) {
- if (!ptr)
- break;
- eprintf("%s: incomplete frame", stream.file);
- }
- }
- if (!ptr)
- break;
- transpose(&stream, buf, image);
- for (ptr = 0; ptr < n; ptr += (size_t)r) {
- r = write(STDOUT_FILENO, image + ptr, n - ptr);
- if (r < 0)
- eprintf("write <stdout>");
- }
+ efflush(stdout, "<stdout>");
+
+ echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, "<stdin>");
+ n = stream.width * stream.height * stream.pixel_size;
+ buf = emalloc(n);
+ image = emalloc(n);
+
+ imgw = stream.width * (imgh = stream.height * stream.pixel_size);
+ memcpy(buf, stream.buf, stream.ptr);
+ while (eread_frame(&stream, buf, n)) {
+ for (b = y = 0; y < imgh; y += stream.pixel_size)
+ for (x = 0; x < imgw; x += imgh)
+ for (i = 0; i < stream.pixel_size; i++)
+ image[x + y + i] = buf[b++];
+ ewriteall(STDOUT_FILENO, image, n, "<stdout>");
}
+ free(buf);
+ free(image);
return 0;
}
diff --git a/src/vu-write-head.c b/src/vu-write-head.c
@@ -1,29 +1,16 @@
/* See LICENSE file for copyright and license details. */
-#include "arg.h"
#include "util.h"
-static void
-usage(void)
-{
- eprintf("usage: %s parameters ...\n", argv0);
-}
+USAGE("parameters ...")
int
main(int argc, char *argv[])
{
- int i;
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND;
-
- if (!argc)
- usage();
+ ENOFLAGS(!argc);
- printf("%s", argv[0]);
- for (i = 0; i < argc; i++)
- printf(" %s", argv[i]);
+ printf("%s", *argv++);
+ while (*argv)
+ printf(" %s", *argv++);
printf("\n%cuivf", 0);
efshut(stdout, "<stdout>");