aboutsummaryrefslogtreecommitdiffstats
path: root/src/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stream.c')
-rw-r--r--src/stream.c446
1 files changed, 54 insertions, 392 deletions
diff --git a/src/stream.c b/src/stream.c
index 52a32dd..3b1340a 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -1,88 +1,14 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
-static inline int
-get_dimension(int status, size_t *out, const char *s, const char *fname, const char *dim)
-{
- char *end;
- errno = 0;
- *out = strtoul(s, &end, 10);
- if (errno == ERANGE && *s != '-')
- enprintf(status, "%s: video is too %s\n", fname, dim);
- return -(errno || *end);
-}
-
-static inline int
-sread(int status, struct stream *stream)
-{
- ssize_t r;
- r = read(stream->fd, stream->buf + stream->ptr, sizeof(stream->buf) - stream->ptr);
- if (r < 0)
- enprintf(status, "read %s:", stream->file);
- if (r == 0)
- return 0;
- stream->ptr += (size_t)r;
- return 1;
-}
-
void
eninit_stream(int status, struct stream *stream)
{
- size_t n;
- char *p = NULL, *w, *h, *f;
-
- fadvise_sequential(stream->fd, 0, 0);
-
- if (stream->fd >= 0) {
- for (stream->ptr = 0; !p; p = memchr(stream->buf, '\n', stream->ptr))
- if (!sread(status, stream))
- goto bad_format;
- } else {
- p = memchr(stream->buf, '\n', stream->ptr);
- }
-
- *p = '\0';
- if (!(w = strchr(stream->buf, ' ')) ||
- !(h = strchr(w + 1, ' ')) ||
- !(f = strchr(h + 1, ' ')))
- goto bad_format;
- *w++ = *h++ = *f++ = '\0';
-
- if (strlen(f) >= sizeof(stream->pixfmt))
- goto bad_format;
- strcpy(stream->pixfmt, f);
- if (get_dimension(status, &stream->frames, stream->buf, stream->file, "long") ||
- get_dimension(status, &stream->width, w, stream->file, "wide") ||
- get_dimension(status, &stream->height, h, stream->file, "tall"))
- goto bad_format;
-
- if (!stream->width)
- eprintf("%s: width is zero\n", stream->file);
- if (!stream->height)
- eprintf("%s: height is zero\n", stream->file);
-
- n = (size_t)(p - stream->buf) + 1;
- memmove(stream->buf, stream->buf + n, stream->ptr -= n);
- while (stream->ptr < 5)
- if (!sread(status, stream))
- goto bad_format;
- if (stream->buf[0] != '\0' ||
- stream->buf[1] != 'u' || stream->buf[2] != 'i' ||
- stream->buf[3] != 'v' || stream->buf[4] != 'f')
- goto bad_format;
- memmove(stream->buf, stream->buf + 5, stream->ptr -= 5);
- stream->headlen = n + 5;
-
- enset_pixel_format(status, stream, NULL);
-
- stream->xptr = 0;
-
- return;
-bad_format:
- enprintf(status, "%s: file format not supported\n", stream->file);
+ int r = libblind_init_stream(stream);
+ if (r)
+ enprintf(status, "%s: %s\n", stream->file, libblind_strerror(r));
}
-
void
enopen_stream(int status, struct stream *stream, const char *file)
{
@@ -91,113 +17,14 @@ enopen_stream(int status, struct stream *stream, const char *file)
eninit_stream(status, stream);
}
-
-int
-set_pixel_format(struct stream *stream, const char *pixfmt)
-{
-#define TEST_ENCODING_AGNOSTIC(FMT) (!strcmp(stream->pixfmt, FMT) || !strcmp(stream->pixfmt, FMT" f"))
-
- if (pixfmt) {
- pixfmt = get_pixel_format(pixfmt, stream->pixfmt[0] ? stream->pixfmt : "xyza");
- if (strlen(pixfmt) >= sizeof(stream->pixfmt))
- return -1;
- strcpy(stream->pixfmt, pixfmt);
- }
-
- stream->n_chan = 4;
- stream->alpha = UNPREMULTIPLIED;
- stream->encoding = DOUBLE;
- stream->endian = HOST;
- stream->alpha_chan = 3;
- stream->luma_chan = -1;
-
- if (!strcmp(stream->pixfmt, "xyza")) {
- stream->space = CIEXYZ;
- } else if (!strcmp(stream->pixfmt, "xyza f")) {
- stream->space = CIEXYZ;
- stream->encoding = FLOAT;
- } else if (!strcmp(stream->pixfmt, "raw0")) {
- stream->space = YUV_NONLINEAR;
- stream->encoding = UINT16;
- stream->endian = LITTLE;
- stream->alpha_chan = 0;
- stream->luma_chan = 1;
- } else if (!strcmp(stream->pixfmt, "raw1")) {
- stream->space = YUV_NONLINEAR;
- stream->encoding = UINT16;
- stream->endian = LITTLE;
- } else if (!strcmp(stream->pixfmt, "raw2a") || !strcmp(stream->pixfmt, "raw2")) {
- stream->space = YUV_NONLINEAR;
- stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
- stream->encoding = UINT16;
- } else if (TEST_ENCODING_AGNOSTIC("raw3") || TEST_ENCODING_AGNOSTIC("raw3a")) {
- stream->space = YUV_NONLINEAR;
- stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
- stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : DOUBLE;
- } else if (TEST_ENCODING_AGNOSTIC("raw4") || TEST_ENCODING_AGNOSTIC("raw4a")) {
- stream->space = SRGB_NONLINEAR;
- stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
- stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : DOUBLE;
- } else if (TEST_ENCODING_AGNOSTIC("raw5") || TEST_ENCODING_AGNOSTIC("raw5a")) {
- stream->space = SRGB;
- stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
- stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : DOUBLE;
- } else {
- return -1;
- }
-
- if (stream->alpha == NO_ALPHA) {
- stream->n_chan -= 1;
- stream->alpha_chan = -1;
- }
-
- if (stream->luma_chan == -1) {
- if (stream->space == CIEXYZ)
- stream->luma_chan = 1;
- else if (stream->space == YUV_NONLINEAR)
- stream->luma_chan = 0;
- }
-
- switch (stream->encoding) {
- case FLOAT:
- stream->chan_size = sizeof(float);
- break;
- case DOUBLE:
- stream->chan_size = sizeof(double);
- break;
- case LONG_DOUBLE:
- stream->chan_size = sizeof(long double);
- break;
- case UINT8:
- stream->chan_size = sizeof(uint8_t);
- break;
- case UINT16:
- stream->chan_size = sizeof(uint16_t);
- break;
- case UINT32:
- stream->chan_size = sizeof(uint32_t);
- break;
- case UINT64:
- stream->chan_size = sizeof(uint64_t);
- break;
- default:
- abort();
- }
-
- stream->pixel_size = stream->n_chan * stream->chan_size;
- stream->row_size = stream->pixel_size * stream->width;
- stream->col_size = stream->pixel_size * stream->height;
- stream->frame_size = stream->pixel_size * stream->height * stream->width;
- return 0;
-
-#undef TEST_ENCODING_AGNOSTIC
-}
-
void
-enset_pixel_format(int status, struct stream *stream, const char *pixfmt)
+enset_pixfmt(int status, struct stream *stream, const char *pixfmt)
{
- if (set_pixel_format(stream, pixfmt)) {
- if (pixfmt)
+ int err;
+ if ((err = set_pixfmt(stream, pixfmt))) {
+ if (err != LIBBLIND_EPIXFMTNOSUPPORT)
+ enprintf(status, "%s: %s\n", stream->file, libblind_strerror(err));
+ else if (pixfmt)
enprintf(status, "pixel format %s is not supported, try xyza\n", pixfmt);
else
enprintf(status, "%s: unsupported pixel format: %s\n",
@@ -223,11 +50,9 @@ dprint_stream_head(int fd, struct stream *stream)
size_t
enread_stream(int status, struct stream *stream, size_t n)
{
- ssize_t r = read(stream->fd, stream->buf + stream->ptr,
- MIN(sizeof(stream->buf) - stream->ptr, n));
+ ssize_t r = libblind_read_stream(stream, n);
if (r < 0)
- enprintf(status, "read %s:", stream->file);
- stream->ptr += (size_t)r;
+ enprintf(status, "read %s: %s\n", stream->file, libblind_strerror((int)r));
return (size_t)r;
}
@@ -246,46 +71,12 @@ eninf_check_fd(int status, int fd, const char *file)
void
encheck_dimensions(int status, const struct stream *stream, enum dimension dimensions, const char *prefix)
{
- size_t n;
-
- if (!stream->pixel_size)
- enprintf(status, "%s: %s%svideo frame doesn't have a pixel size\n",
- stream->file, prefix ? prefix : "",
- (prefix && *prefix) ? " " : "");
-
- n = SIZE_MAX / stream->pixel_size;
-
- if ((dimensions & WIDTH) && stream->width > n)
- enprintf(status, "%s: %s%svideo frame is too wide\n",
- stream->file, prefix ? prefix : "",
- (prefix && *prefix) ? " " : "");
-
- if ((dimensions & HEIGHT) && stream->height > n)
- enprintf(status, "%s: %s%svideo frame is too wide\n",
- stream->file, prefix ? prefix : "",
- (prefix && *prefix) ? " " : "");
-
- if (!stream->width || !stream->height)
- return;
-
- if ((dimensions & (WIDTH | HEIGHT)) == (WIDTH | HEIGHT)) {
- if (stream->width > n / stream->height)
- enprintf(status, "%s: %s%svideo frame is too large\n",
- stream->file, prefix ? prefix : "",
- (prefix && *prefix) ? " " : "");
- }
-
- if (!(dimensions & LENGTH))
- return;
- if (dimensions & WIDTH)
- n /= stream->width;
- if (dimensions & HEIGHT)
- n /= stream->height;
-
- if (stream->frames > n)
- enprintf(status, "%s: %s%svideo is too large\n",
- stream->file, prefix ? prefix : "",
- (prefix && *prefix) ? " " : "");
+ int r = libblind_check_dimensions(stream, dimensions);
+ if (r < 0)
+ enprintf(status, "%s: %s%s%s\n",
+ stream->file, prefix ? prefix : "",
+ (prefix && *prefix) ? ": " : "",
+ libblind_strerror(r));
}
@@ -300,76 +91,6 @@ encheck_compat(int status, const struct stream *a, const struct stream *b)
const char *
-get_pixel_format(const char *specified, const char *current)
-{
- enum colour_space space = CIEXYZ;
- enum alpha alpha = UNPREMULTIPLIED;
- enum encoding encoding = UINT16;
- int level = -1;
- size_t n = strlen(specified);
-
- if ((n >= 2 && !strcmp(specified - 2, " f")) ||
- !strcmp(specified, "raw0") || !strcmp(specified, "raw1") ||
- !strcmp(specified, "raw2") || !strcmp(specified, "raw2a"))
- return specified;
-
- if (!strcmp(current, "xyza")) space = CIEXYZ, encoding = DOUBLE;
- else if (!strcmp(current, "xyza f")) space = CIEXYZ, encoding = FLOAT;
- else if (!strcmp(current, "raw0")) level = 0;
- else if (!strcmp(current, "raw1")) level = 1;
- else if (!strcmp(current, "raw2")) level = 2, alpha = NO_ALPHA;
- else if (!strcmp(current, "raw2a")) level = 2;
- else if (!strcmp(current, "raw3")) level = 3, encoding = DOUBLE, alpha = NO_ALPHA;
- else if (!strcmp(current, "raw3a")) level = 3, encoding = DOUBLE;
- else if (!strcmp(current, "raw3 f")) level = 3, encoding = FLOAT, alpha = NO_ALPHA;
- else if (!strcmp(current, "raw3a f")) level = 3, encoding = FLOAT;
- else if (!strcmp(current, "raw4")) level = 4, encoding = DOUBLE, alpha = NO_ALPHA;
- else if (!strcmp(current, "raw4a")) level = 4, encoding = DOUBLE;
- else if (!strcmp(current, "raw4 f")) level = 4, encoding = FLOAT, alpha = NO_ALPHA;
- else if (!strcmp(current, "raw4a f")) level = 4, encoding = FLOAT;
- else if (!strcmp(current, "raw5")) level = 5, encoding = DOUBLE, alpha = NO_ALPHA;
- else if (!strcmp(current, "raw5a")) level = 5, encoding = DOUBLE;
- else if (!strcmp(current, "raw5 f")) level = 5, encoding = FLOAT, alpha = NO_ALPHA;
- else if (!strcmp(current, "raw5a f")) level = 5, encoding = FLOAT;
- else
- return specified;
-
- if (!strcmp(specified, "f")) encoding = FLOAT;
- else if (!strcmp(specified, "!f")) encoding = DOUBLE;
- else if (!strcmp(specified, "xyza")) level = -1, alpha = UNPREMULTIPLIED, space = CIEXYZ;
- else if (!strcmp(specified, "raw3")) level = 3, alpha = NO_ALPHA;
- else if (!strcmp(specified, "raw3a")) level = 3, alpha = UNPREMULTIPLIED;
- else if (!strcmp(specified, "raw4")) level = 4, alpha = NO_ALPHA;
- else if (!strcmp(specified, "raw4a")) level = 4, alpha = UNPREMULTIPLIED;
- else if (!strcmp(specified, "raw5")) level = 5, alpha = NO_ALPHA;
- else if (!strcmp(specified, "raw5a")) level = 5, alpha = UNPREMULTIPLIED;
- else if (!strcmp(specified, "xyza !f")) return "xyza";
- else if (!strcmp(specified, "raw3 !f")) return "raw3";
- else if (!strcmp(specified, "raw3a !f")) return "raw3a";
- else if (!strcmp(specified, "raw4 !f")) return "raw4";
- else if (!strcmp(specified, "raw4a !f")) return "raw4a";
- else if (!strcmp(specified, "raw5 !f")) return "raw5";
- else if (!strcmp(specified, "raw5a !f")) return "raw5a";
- else
- return specified;
-
- if (level == 0 && encoding == UINT16) return "raw0";
- else if (level == 1 && encoding == UINT16) return "raw1";
- else if (level == 2 && encoding == UINT16) return alpha ? "raw2a" : "raw2";
- else if (level == 3 && encoding == DOUBLE) return alpha ? "raw3a" : "raw3";
- else if (level == 3 && encoding == FLOAT) return alpha ? "raw3a f" : "raw3 f";
- else if (level == 4 && encoding == DOUBLE) return alpha ? "raw4a" : "raw4";
- else if (level == 4 && encoding == FLOAT) return alpha ? "raw4a f" : "raw4 f";
- else if (level == 5 && encoding == DOUBLE) return alpha ? "raw5a" : "raw5";
- else if (level == 5 && encoding == FLOAT) return alpha ? "raw5a f" : "raw5 f";
- else if (level < 0 && space == CIEXYZ && alpha == UNPREMULTIPLIED)
- return encoding == FLOAT ? "xyza f" : encoding == DOUBLE ? "xyza" : specified;
- else
- return specified;
-}
-
-
-const char *
nselect_print_format(int status, const char *format, enum encoding encoding, const char *fmt)
{
static char retbuf[512];
@@ -526,125 +247,66 @@ check_done:
int
enread_segment(int status, struct stream *stream, void *buf, size_t n)
{
- char *buffer = buf;
- ssize_t r;
- size_t m;
-
- if (stream->ptr) {
- m = MIN(stream->ptr, n);
- memcpy(buffer + stream->xptr, stream->buf, m);
- memmove(stream->buf, stream->buf + m, stream->ptr -= m);
- stream->xptr += m;
- }
-
- for (; stream->xptr < n; stream->xptr += (size_t)r) {
- r = read(stream->fd, buffer + stream->xptr, n - stream->xptr);
- if (r < 0) {
- enprintf(status, "read %s:", stream->file);
- } else if (r == 0) {
- if (!stream->xptr)
- break;
- enprintf(status, "%s: incomplete frame", stream->file);
- }
- }
-
- if (!stream->xptr)
- return 0;
- stream->xptr -= n;
- return 1;
+ int r = libblind_read_segment(stream, buf, n);
+ if (r < 0)
+ enprintf(status, "%s: %s\n", stream->file, libblind_strerror(r));
+ return r;
}
-
size_t
ensend_frames(int status, struct stream *stream, int outfd, size_t frames, const char *outfname)
{
- size_t h, w, p, n, ret;
-
- for (ret = 0; ret < frames; ret++) {
- for (p = stream->pixel_size; p; p--) {
- for (h = stream->height; h; h--) {
- for (w = stream->width; w; w -= n) {
- if (!stream->ptr && !enread_stream(status, stream, w))
- goto done;
- n = MIN(stream->ptr, w);
- if (outfd >= 0)
- enwriteall(status, outfd, stream->buf, n, outfname);
- memmove(stream->buf, stream->buf + n, stream->ptr -= n);
- }
- }
- }
+ int outfailed;
+ int r = libblind_send_frames(stream, outfd, frames, &outfailed);
+ if (r < 0) {
+ if (!outfailed)
+ enprintf(status, "%s:", stream->file);
+ else if (outfname)
+ enprintf(status, "%s:", outfname);
}
-
- return ret;
-done:
- if (p != stream->pixel_size || h != stream->height || w != stream->width)
- enprintf(status, "%s: incomplete frame", stream->file);
- return ret;
+ return r;
}
-
size_t
ensend_rows(int status, struct stream *stream, int outfd, size_t rows, const char *outfname)
{
- size_t w, p, n, ret;
-
- for (ret = 0; ret < rows; ret++) {
- for (p = stream->pixel_size; p; p--) {
- for (w = stream->width; w; w -= n) {
- if (!stream->ptr && !enread_stream(status, stream, w))
- goto done;
- n = MIN(stream->ptr, w);
- if (outfd >= 0)
- enwriteall(status, outfd, stream->buf, n, outfname);
- memmove(stream->buf, stream->buf + n, stream->ptr -= n);
- }
- }
+ int outfailed;
+ int r = libblind_send_rows(stream, outfd, rows, &outfailed);
+ if (r < 0) {
+ if (!outfailed)
+ enprintf(status, "%s:", stream->file);
+ else if (outfname)
+ enprintf(status, "%s:", outfname);
}
-
- return ret;
-done:
- if (p != stream->pixel_size || w != stream->width)
- enprintf(status, "%s: incomplete row", stream->file);
- return ret;
+ return r;
}
-
size_t
ensend_pixels(int status, struct stream *stream, int outfd, size_t pixels, const char *outfname)
{
- size_t p, n, ret;
-
- for (ret = 0; ret < pixels; ret++) {
- for (p = stream->pixel_size; p; p -= n) {
- if (!stream->ptr && !enread_stream(status, stream, p))
- goto done;
- n = MIN(stream->ptr, p);
- if (outfd >= 0)
- enwriteall(status, outfd, stream->buf, n, outfname);
- memmove(stream->buf, stream->buf + n, stream->ptr -= n);
- }
+ int outfailed;
+ int r = libblind_send_pixels(stream, outfd, pixels, &outfailed);
+ if (r < 0) {
+ if (!outfailed)
+ enprintf(status, "%s:", stream->file);
+ else if (outfname)
+ enprintf(status, "%s:", outfname);
}
-
- return ret;
-done:
- if (p != stream->pixel_size)
- enprintf(status, "%s: incomplete pixel", stream->file);
- return ret;
+ return r;
}
-
int
ensend_stream(int status, struct stream *stream, int outfd, const char *outfname)
{
- do {
- if (writeall(outfd, stream->buf, stream->ptr)) {
- if (outfname)
- eprintf("write %s:", outfname);
- return -1;
- }
- stream->ptr = 0;
- } while (enread_stream(status, stream, SIZE_MAX));
- return 0;
+ int outfailed;
+ int r = libblind_send_stream(stream, outfd, &outfailed);
+ if (r < 0) {
+ if (!outfailed)
+ enprintf(status, "%s:", stream->file);
+ else if (outfname)
+ enprintf(status, "%s:", outfname);
+ }
+ return r;
}