Moving zlib stream interface

Moving the zlib streaming interface out of archive_file and into
trans_stream, including updating the png support to use the new
trans_stream interface. archive_file_zlib itself still needs updating.
This commit is contained in:
Gregor Richards 2016-11-26 10:47:24 -05:00
parent f27476b4ef
commit ac50e17f50
7 changed files with 107 additions and 91 deletions

View File

@ -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

View File

@ -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,

View File

@ -32,7 +32,7 @@
#include <boolean.h>
#include <formats/image.h>
#include <formats/rpng.h>
#include <file/archive_file.h>
#include <streams/trans_stream.h>
#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);
}

View File

@ -26,7 +26,7 @@
#include <encodings/crc32.h>
#include <streams/file_stream.h>
#include <file/archive_file.h>
#include <streams/trans_stream.h>
#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))

View File

@ -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);

View File

@ -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
};

View File

@ -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 = {