diff --git a/Makefile.common b/Makefile.common index 1944d4563a..f3cfaf753a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -977,7 +977,9 @@ endif # Compression/Archive -OBJ += $(LIBRETRO_COMM_DIR)/file/archive_file.o +OBJ += $(LIBRETRO_COMM_DIR)/file/archive_file.o \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream.o \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream_pipe.o ifeq ($(HAVE_7ZIP),1) CFLAGS += -I$(DEPS_DIR)/7zip @@ -1003,7 +1005,8 @@ endif ifeq ($(HAVE_ZLIB), 1) - OBJ += $(LIBRETRO_COMM_DIR)/file/archive_file_zlib.o + OBJ += $(LIBRETRO_COMM_DIR)/file/archive_file_zlib.o \ + $(LIBRETRO_COMM_DIR)/streams/trans_stream_zlib.o OBJ += $(ZLIB_OBJS) DEFINES += -DHAVE_ZLIB HAVE_COMPRESSION = 1 diff --git a/libretro-common/file/archive_file_7z.c b/libretro-common/file/archive_file_7z.c index 992b2cbffd..b1234eabc9 100644 --- a/libretro-common/file/archive_file_7z.c +++ b/libretro-common/file/archive_file_7z.c @@ -424,17 +424,8 @@ static uint32_t sevenzip_stream_crc32_calculate(uint32_t crc, const struct file_archive_file_backend sevenzip_backend = { sevenzip_stream_new, sevenzip_stream_free, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, sevenzip_stream_decompress_data_to_file_init, sevenzip_stream_decompress_data_to_file_iterate, - NULL, - NULL, - NULL, sevenzip_stream_crc32_calculate, sevenzip_file_read, sevenzip_parse_file_init, diff --git a/libretro-common/formats/png/rpng.c b/libretro-common/formats/png/rpng.c index e1204414f0..2ad8c9017d 100644 --- a/libretro-common/formats/png/rpng.c +++ b/libretro-common/formats/png/rpng.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include "rpng_internal.h" @@ -112,7 +112,8 @@ struct rpng_process unsigned pos; } pass; void *stream; - const struct file_archive_file_backend *stream_backend; + size_t avail_in, avail_out, total_out; + const struct trans_stream_backend *stream_backend; }; struct rpng @@ -538,7 +539,7 @@ static int png_reverse_filter_init(const struct png_ihdr *ihdr, png_pass_geom(&pngp->ihdr, pngp->pass.width, pngp->pass.height, NULL, NULL, &pngp->pass.size); - if (pngp->pass.size > pngp->stream_backend->stream_get_total_out(pngp->stream)) + if (pngp->pass.size > pngp->total_out) { free(pngp->data); return -1; @@ -554,7 +555,7 @@ static int png_reverse_filter_init(const struct png_ihdr *ihdr, png_pass_geom(ihdr, ihdr->width, ihdr->height, &pngp->bpp, &pngp->pitch, &pass_size); - if (pngp->stream_backend->stream_get_total_out(pngp->stream) < pass_size) + if (pngp->total_out < pass_size) return -1; pngp->restore_buf_size = 0; @@ -711,7 +712,7 @@ static int png_reverse_filter_adam7_iterate(uint32_t **data_, pngp->inflate_buf += pngp->pass.size; pngp->adam7_restore_buf_size += pngp->pass.size; - pngp->stream_backend->stream_decrement_total_out(pngp->stream, pngp->pass.size); + pngp->total_out -= pngp->pass.size; png_reverse_filter_adam7_deinterlace_pass(data, ihdr, pngp->data, pngp->pass.width, pngp->pass.height, &passes[pngp->pass.pos]); @@ -768,30 +769,31 @@ static int png_reverse_filter_iterate(rpng_t *rpng, uint32_t **data) static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng, uint32_t **data, unsigned *width, unsigned *height) { - int zstatus; + bool zstatus; + enum trans_stream_error terror; + uint32_t rd, wn; struct rpng_process *process = (struct rpng_process*)rpng->process; - bool to_continue = (process->stream_backend->stream_get_avail_in(process->stream) > 0 - && process->stream_backend->stream_get_avail_out(process->stream) > 0); + bool to_continue = (process->avail_in > 0 + && process->avail_out > 0); if (!to_continue) goto end; - zstatus = process->stream_backend->stream_decompress_data_to_file_iterate(process->stream); + zstatus = process->stream_backend->trans(process->stream, false, &rd, &wn, &terror); - switch (zstatus) - { - case 1: - goto end; - case -1: - goto error; - default: - break; - } + if (!zstatus && terror != TRANS_STREAM_ERROR_BUFFER_FULL) + goto error; - return 0; + process->avail_in -= rd; + process->avail_out -= wn; + process->total_out += wn; + + if (terror) + return 0; end: process->stream_backend->stream_free(process->stream); + process->stream = NULL; *width = rpng->ihdr.width; *height = rpng->ihdr.height; @@ -870,7 +872,7 @@ static struct rpng_process *rpng_process_init(rpng_t *rpng, unsigned *width, uns if (!process) return NULL; - process->stream_backend = file_archive_get_zlib_file_backend(); + process->stream_backend = trans_stream_get_zlib_inflate_backend(); png_pass_geom(&rpng->ihdr, rpng->ihdr.width, rpng->ihdr.height, NULL, NULL, &process->inflate_buf_size); @@ -885,23 +887,22 @@ static struct rpng_process *rpng_process_init(rpng_t *rpng, unsigned *width, uns return NULL; } - if (!process->stream_backend->stream_decompress_init(process->stream)) - { - free(process); - return NULL; - } - inflate_buf = (uint8_t*)malloc(process->inflate_buf_size); if (!inflate_buf) goto error; process->inflate_buf = inflate_buf; - process->stream_backend->stream_set( + process->avail_in = rpng->idat_buf.size; + process->avail_out = process->inflate_buf_size; + process->total_out = 0; + process->stream_backend->set_in( process->stream, - rpng->idat_buf.size, - process->inflate_buf_size, rpng->idat_buf.data, - process->inflate_buf); + rpng->idat_buf.size); + process->stream_backend->set_out( + process->stream, + process->inflate_buf, + process->inflate_buf_size); return process; @@ -1130,7 +1131,8 @@ void rpng_free(rpng_t *rpng) { if (rpng->process->stream_backend) rpng->process->stream_backend->stream_free(rpng->process->stream); - free(rpng->process->stream); + else + free(rpng->process->stream); } free(rpng->process); } diff --git a/libretro-common/formats/png/rpng_encode.c b/libretro-common/formats/png/rpng_encode.c index 000e876a98..f580ed2646 100644 --- a/libretro-common/formats/png/rpng_encode.c +++ b/libretro-common/formats/png/rpng_encode.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include "rpng_internal.h" @@ -213,7 +213,7 @@ static bool rpng_save_image(const char *path, bool ret = true; struct png_ihdr ihdr = {0}; - const struct file_archive_file_backend *stream_backend = NULL; + const struct trans_stream_backend *stream_backend = NULL; size_t encode_buf_size = 0; uint8_t *encode_buf = NULL; uint8_t *deflate_buf = NULL; @@ -225,11 +225,13 @@ static bool rpng_save_image(const char *path, uint8_t *prev_encoded = NULL; uint8_t *encode_target = NULL; void *stream = NULL; + uint32_t total_in = 0; + uint32_t total_out = 0; RFILE *file = filestream_open(path, RFILE_MODE_WRITE, -1); if (!file) GOTO_END_ERROR(); - stream_backend = file_archive_get_zlib_file_backend(); + stream_backend = trans_stream_get_zlib_deflate_backend(); if (filestream_write(file, png_magic, sizeof(png_magic)) != sizeof(png_magic)) GOTO_END_ERROR(); @@ -328,26 +330,23 @@ static bool rpng_save_image(const char *path, if (!stream) GOTO_END_ERROR(); - stream_backend->stream_set( + stream_backend->set_in( stream, - encode_buf_size, - encode_buf_size * 2, encode_buf, - deflate_buf + 8); + encode_buf_size); + stream_backend->set_out( + stream, + deflate_buf + 8, + encode_buf_size * 2); - stream_backend->stream_compress_init(stream, 9); - - if (stream_backend->stream_compress_data_to_file(stream) != 1) + if (!stream_backend->trans(stream, true, &total_in, &total_out, NULL)) { - stream_backend->stream_compress_free(stream); GOTO_END_ERROR(); } - stream_backend->stream_compress_free(stream); - memcpy(deflate_buf + 4, "IDAT", 4); - dword_write_be(deflate_buf + 0, ((uint32_t)stream_backend->stream_get_total_out(stream))); - if (!png_write_idat(file, deflate_buf, ((size_t)stream_backend->stream_get_total_out(stream) + 8))) + dword_write_be(deflate_buf + 0, ((uint32_t)total_out)); + if (!png_write_idat(file, deflate_buf, ((size_t)total_out + 8))) GOTO_END_ERROR(); if (!png_write_iend(file)) diff --git a/libretro-common/include/file/archive_file.h b/libretro-common/include/file/archive_file.h index 048387c857..407bc3cfc7 100644 --- a/libretro-common/include/file/archive_file.h +++ b/libretro-common/include/file/archive_file.h @@ -121,19 +121,9 @@ struct file_archive_file_backend { void *(*stream_new)(void); void (*stream_free)(void *); - void (*stream_set)(void *, uint32_t, uint32_t, - const uint8_t *, uint8_t *); - uint32_t (*stream_get_avail_in)(void*); - uint32_t (*stream_get_avail_out)(void*); - uint64_t (*stream_get_total_out)(void*); - void (*stream_decrement_total_out)(void *, unsigned); - bool (*stream_decompress_init)(void *); bool (*stream_decompress_data_to_file_init)( file_archive_file_handle_t *, const uint8_t *, uint32_t, uint32_t); int (*stream_decompress_data_to_file_iterate)(void *); - void (*stream_compress_init)(void *, int); - void (*stream_compress_free)(void *); - int (*stream_compress_data_to_file)(void *); uint32_t (*stream_crc_calculate)(uint32_t, const uint8_t *, size_t); int (*compressed_file_read)(const char *path, const char *needle, void **buf, const char *optional_outfile); diff --git a/libretro-common/include/streams/trans_stream.h b/libretro-common/include/streams/trans_stream.h index 6b0ec78feb..cc8d46da08 100644 --- a/libretro-common/include/streams/trans_stream.h +++ b/libretro-common/include/streams/trans_stream.h @@ -38,9 +38,10 @@ enum trans_stream_error { TRANS_STREAM_ERROR_NONE = 0, - TRANS_STREAM_ERROR_ALLOCATION_FAILURE, - TRANS_STREAM_ERROR_INVALID, - TRANS_STREAM_ERROR_BUFFER_FULL, + TRANS_STREAM_ERROR_AGAIN, /* more work to do */ + TRANS_STREAM_ERROR_ALLOCATION_FAILURE, /* malloc failure */ + TRANS_STREAM_ERROR_INVALID, /* invalid state */ + TRANS_STREAM_ERROR_BUFFER_FULL, /* output buffer full */ TRANS_STREAM_ERROR_OTHER }; diff --git a/libretro-common/streams/trans_stream_zlib.c b/libretro-common/streams/trans_stream_zlib.c index a175b9fc73..f111a1491a 100644 --- a/libretro-common/streams/trans_stream_zlib.c +++ b/libretro-common/streams/trans_stream_zlib.c @@ -60,7 +60,7 @@ static void zlib_deflate_set_in(void *data, const uint8_t *in, uint32_t in_size) z->z.avail_in = in_size; if (!z->inited) { - deflateInit(&z->z, Z_DEFAULT_COMPRESSION); + deflateInit(&z->z, 9); z->inited = true; } } @@ -72,7 +72,7 @@ static void zlib_inflate_set_in(void *data, const uint8_t *in, uint32_t in_size) z->z.avail_in = in_size; if (!z->inited) { - deflateInit(&z->z, Z_DEFAULT_COMPRESSION); + inflateInit(&z->z); z->inited = true; } } @@ -89,46 +89,61 @@ static bool zlib_deflate_trans( uint32_t *rd, uint32_t *wn, enum trans_stream_error *error) { - int ret; + int zret; + bool ret; uint32_t pre_avail_in, pre_avail_out; struct zlib_trans_stream *zt = (struct zlib_trans_stream *) data; z_stream *z = &zt->z; if (!zt->inited) { - deflateInit(z, Z_DEFAULT_COMPRESSION); + deflateInit(z, 9); zt->inited = true; } pre_avail_in = z->avail_in; pre_avail_out = z->avail_out; - ret = deflate(z, flush ? Z_FINISH : Z_NO_FLUSH); + zret = deflate(z, flush ? Z_FINISH : Z_NO_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) + if (zret == Z_OK) + { + if (error) + *error = TRANS_STREAM_ERROR_AGAIN; + } + else if (zret == Z_STREAM_END) + { + if (error) + *error = TRANS_STREAM_ERROR_NONE; + } + else { if (error) *error = TRANS_STREAM_ERROR_OTHER; return false; } + ret = true; - *error = TRANS_STREAM_ERROR_NONE; if (z->avail_out == 0) { /* Filled buffer, maybe an error */ if (z->avail_in != 0) - *error = TRANS_STREAM_ERROR_BUFFER_FULL; + { + ret = false; + if (error) + *error = TRANS_STREAM_ERROR_BUFFER_FULL; + } } - *rd = z->avail_in - pre_avail_in; - *wn = z->avail_out - pre_avail_out; + *rd = pre_avail_in - z->avail_in; + *wn = pre_avail_out - z->avail_out; - if (flush && !*error) + if (flush && zret == Z_STREAM_END) { deflateEnd(z); zt->inited = false; } - return !*error; + return ret; } static bool zlib_inflate_trans( @@ -136,7 +151,8 @@ static bool zlib_inflate_trans( uint32_t *rd, uint32_t *wn, enum trans_stream_error *error) { - int ret; + int zret; + bool ret; uint32_t pre_avail_in, pre_avail_out; struct zlib_trans_stream *zt = (struct zlib_trans_stream *) data; z_stream *z = &zt->z; @@ -149,33 +165,47 @@ static bool zlib_inflate_trans( pre_avail_in = z->avail_in; pre_avail_out = z->avail_out; - ret = inflate(z, flush ? Z_FINISH : Z_NO_FLUSH); + zret = inflate(z, flush ? Z_FINISH : Z_NO_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) + if (zret == Z_OK) + { + if (error) + *error = TRANS_STREAM_ERROR_AGAIN; + } + else if (zret == Z_STREAM_END) + { + if (error) + *error = TRANS_STREAM_ERROR_NONE; + } + else { if (error) *error = TRANS_STREAM_ERROR_OTHER; return false; } + ret = true; - *error = TRANS_STREAM_ERROR_NONE; if (z->avail_out == 0) { /* Filled buffer, maybe an error */ if (z->avail_in != 0) - *error = TRANS_STREAM_ERROR_BUFFER_FULL; + { + ret = false; + if (error) + *error = TRANS_STREAM_ERROR_BUFFER_FULL; + } } - *rd = z->avail_in - pre_avail_in; - *wn = z->avail_out - pre_avail_out; + *rd = pre_avail_in - z->avail_in; + *wn = pre_avail_out - z->avail_out; - if (flush && !*error) + if (flush && zret == Z_STREAM_END) { inflateEnd(z); zt->inited = false; } - return !*error; + return ret; } const struct trans_stream_backend zlib_deflate_backend = {