diff options
Diffstat (limited to '')
| -rw-r--r-- | src/stream.c | 446 |
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; } |
