From 5a5c56c99b0cbdf80c51f0c514e109a55420bc0d Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Wed, 15 Sep 2021 23:31:57 +0100 Subject: [PATCH] Update libsmacker to 1.2.0r43 --- 3rdParty/libsmacker/README | 10 +- 3rdParty/libsmacker/smacker.c | 1700 ++++++++++++++++----------- 3rdParty/libsmacker/smacker.h | 22 +- 3rdParty/libsmacker/smk_bitstream.c | 119 -- 3rdParty/libsmacker/smk_bitstream.h | 50 - 3rdParty/libsmacker/smk_hufftree.c | 425 ------- 3rdParty/libsmacker/smk_hufftree.h | 88 -- 3rdParty/libsmacker/smk_malloc.h | 33 +- CMakeLists.txt | 2 - 9 files changed, 1056 insertions(+), 1393 deletions(-) delete mode 100644 3rdParty/libsmacker/smk_bitstream.c delete mode 100644 3rdParty/libsmacker/smk_bitstream.h delete mode 100644 3rdParty/libsmacker/smk_hufftree.c delete mode 100644 3rdParty/libsmacker/smk_hufftree.h diff --git a/3rdParty/libsmacker/README b/3rdParty/libsmacker/README index 56446fa0f..5f9840317 100644 --- a/3rdParty/libsmacker/README +++ b/3rdParty/libsmacker/README @@ -1,10 +1,10 @@ libsmacker A C library for decoding .smk Smacker Video files -version 1.1.1 -2020-01-05 +version 1.2.0 +2021-06-02 -(c) Greg Kennedy 2013-2020 +(c) Greg Kennedy 2013-2021 http://libsmacker.sourceforge.net ---- @@ -32,6 +32,10 @@ Though the libraries are "bulletproofed" the sample apps are not: be cautious if --- Changelog --- +1.2.0 +* Major refactor of data structures for performance +* Merge all files into a single unified .c source file +* Support audio-only .smk files 1.1.1 * Re-license under LGPL 2.1 1.1 diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 63298610b..eef6e7b75 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1,6 +1,6 @@ /** libsmacker - A C library for decoding .smk Smacker Video files - Copyright (C) 2012-2017 Greg Kennedy + Copyright (C) 2012-2021 Greg Kennedy See smacker.h for more information. @@ -11,23 +11,491 @@ #include "smacker.h" -/* safe malloc and free */ #include "smk_malloc.h" -/* data structures */ -#include "smk_bitstream.h" -#include "smk_hufftree.h" +#include +#include +#include +#include + +/* ************************************************************************* */ +/* BITSTREAM Structure */ +/* ************************************************************************* */ +/* Wraps a block of memory and adds functions to read 1 or 8 bits at a time */ +struct smk_bit_t { + const unsigned char * buffer, * end; + unsigned int bit_num; +}; + +/* ************************************************************************* */ +/* BITSTREAM Functions */ +/* ************************************************************************* */ +/** Initialize a bitstream wrapper */ +static void smk_bs_init(struct smk_bit_t * const bs, const unsigned char * const b, const size_t size) +{ + /* null check */ + assert(bs); + assert(b); + /* set up the pointer to bitstream start and end, and set the bit pointer to 0 */ + bs->buffer = b; + bs->end = b + size; + bs->bit_num = 0; +} + +/* Reads a bit + Returns -1 if error encountered */ +static int smk_bs_read_1(struct smk_bit_t * const bs) +{ + int ret; + /* null check */ + assert(bs); + + /* don't die when running out of bits, but signal */ + if (bs->buffer >= bs->end) { + fputs("libsmacker::smk_bs_read_1(): ERROR: bitstream exhausted.\n", stderr); + return -1; + } + + /* get next bit and store for return */ + ret = (*bs->buffer >> bs->bit_num) & 1; + + /* advance to next bit */ + if (bs->bit_num >= 7) { + /* Out of bits in this byte: next! */ + bs->buffer ++; + bs->bit_num = 0; + } else + bs->bit_num ++; + + return ret; +} + +/* Reads a byte + Returns -1 if error. */ +static int smk_bs_read_8(struct smk_bit_t * const bs) +{ + /* null check */ + assert(bs); + + /* don't die when running out of bits, but signal */ + if (bs->buffer + (bs->bit_num > 0) >= bs->end) { + fputs("libsmacker::smk_bs_read_8(): ERROR: bitstream exhausted.\n", stderr); + return -1; + } + + if (bs->bit_num) { + /* unaligned read */ + int ret = *bs->buffer >> bs->bit_num; + bs->buffer ++; + return ret | (*bs->buffer << (8 - bs->bit_num) & 0xFF); + } + + /* aligned read */ + return *bs->buffer++; +} + +/* ************************************************************************* */ +/* HUFF8 Structure */ +/* ************************************************************************* */ +#define SMK_HUFF8_BRANCH 0x8000 +#define SMK_HUFF8_LEAF_MASK 0x7FFF + +struct smk_huff8_t { + /* Unfortunately, smk files do not store the alloc size of a small tree. + 511 entries is the pessimistic case (N codes and N-1 branches, + with N=256 for 8 bits) */ + size_t size; + unsigned short tree[511]; +}; + +/* ************************************************************************* */ +/* HUFF8 Functions */ +/* ************************************************************************* */ +/* Recursive sub-func for building a tree into an array. */ +static int _smk_huff8_build_rec(struct smk_huff8_t * const t, struct smk_bit_t * const bs) +{ + int bit, value; + assert(t); + assert(bs); + + /* Make sure we aren't running out of bounds */ + if (t->size >= 511) { + fputs("libsmacker::_smk_huff8_build_rec() - ERROR: size exceeded\n", stderr); + return 0; + } + + /* Read the next bit */ + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::_smk_huff8_build_rec() - ERROR: get_bit returned -1\n", stderr); + return 0; + } + + if (bit) { + /* Bit set: this forms a Branch node. + what we have to do is build the left-hand branch, + assign the "jump" address, + then build the right hand branch from there. + */ + /* track the current index */ + value = t->size ++; + + /* go build the left branch */ + if (! _smk_huff8_build_rec(t, bs)) { + fputs("libsmacker::_smk_huff8_build_rec() - ERROR: failed to build left sub-tree\n", stderr); + return 0; + } + + /* now go back to our current location, and + mark our location as a "jump" */ + t->tree[value] = SMK_HUFF8_BRANCH | t->size; + + /* continue building the right side */ + if (! _smk_huff8_build_rec(t, bs)) { + fputs("libsmacker::_smk_huff8_build_rec() - ERROR: failed to build right sub-tree\n", stderr); + return 0; + } + } else { + /* Bit unset signifies a Leaf node. */ + /* Attempt to read value */ + if ((value = smk_bs_read_8(bs)) < 0) { + fputs("libsmacker::_smk_huff8_build_rec() - ERROR: get_byte returned -1\n", stderr); + return 0; + } + + /* store to tree */ + t->tree[t->size ++] = value; + } + + return 1; +} + +/** + Build an 8-bit Hufftree out of a Bitstream. +*/ +static int smk_huff8_build(struct smk_huff8_t * const t, struct smk_bit_t * const bs) +{ + int bit; + /* null check */ + assert(t); + assert(bs); + + /* Smacker huff trees begin with a set-bit. */ + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::smk_huff8_build() - ERROR: initial get_bit returned -1\n", stderr); + return 0; + } + + /* OK to fill out the struct now */ + t->size = 0; + + /* First bit indicates whether a tree is present or not. */ + /* Very small or audio-only files may have no tree. */ + if (bit) { + if (! _smk_huff8_build_rec(t, bs)) { + fputs("libsmacker::smk_huff8_build() - ERROR: tree build failed\n", stderr); + return 0; + } + } else + t->tree[0] = 0; + + /* huff trees end with an unset-bit */ + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::smk_huff8_build() - ERROR: final get_bit returned -1\n", stderr); + return 0; + } + + /* a 0 is expected here, a 1 generally indicates a problem! */ + if (bit) { + fputs("libsmacker::smk_huff8_build() - ERROR: final get_bit returned 1\n", stderr); + return 0; + } + + return 1; +} + +/* Look up an 8-bit value from a basic huff tree. + Return -1 on error. */ +static int smk_huff8_lookup(const struct smk_huff8_t * const t, struct smk_bit_t * const bs) +{ + int bit, index = 0; + /* null check */ + assert(t); + assert(bs); + + while (t->tree[index] & SMK_HUFF8_BRANCH) { + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::smk_huff8_lookup() - ERROR: get_bit returned -1\n", stderr); + return -1; + } + + if (bit) { + /* take the right branch */ + index = t->tree[index] & SMK_HUFF8_LEAF_MASK; + } else { + /* take the left branch */ + index ++; + } + } + + /* at leaf node. return the value at this point. */ + return t->tree[index]; +} + +/* ************************************************************************* */ +/* HUFF16 Structure */ +/* ************************************************************************* */ +#define SMK_HUFF16_BRANCH 0x80000000 +#define SMK_HUFF16_CACHE 0x40000000 +#define SMK_HUFF16_LEAF_MASK 0x3FFFFFFF + +struct smk_huff16_t { + unsigned int * tree; + size_t size; + + /* recently-used values cache */ + unsigned short cache[3]; +}; + +/* ************************************************************************* */ +/* HUFF16 Functions */ +/* ************************************************************************* */ +/* Recursive sub-func for building a tree into an array. */ +static int _smk_huff16_build_rec(struct smk_huff16_t * const t, struct smk_bit_t * const bs, const struct smk_huff8_t * const low8, const struct smk_huff8_t * const hi8, const size_t limit) +{ + int bit, value; + assert(t); + assert(bs); + assert(low8); + assert(hi8); + + /* Make sure we aren't running out of bounds */ + if (t->size >= limit) { + fputs("libsmacker::_smk_huff16_build_rec() - ERROR: size exceeded\n", stderr); + return 0; + } + + /* Read the first bit */ + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::_smk_huff16_build_rec() - ERROR: get_bit returned -1\n", stderr); + return 0; + } + + if (bit) { + /* See tree-in-array explanation for HUFF8 above */ + /* track the current index */ + value = t->size ++; + + /* go build the left branch */ + if (! _smk_huff16_build_rec(t, bs, low8, hi8, limit)) { + fputs("libsmacker::_smk_huff16_build_rec() - ERROR: failed to build left sub-tree\n", stderr); + return 0; + } + + /* now go back to our current location, and + mark our location as a "jump" */ + t->tree[value] = SMK_HUFF16_BRANCH | t->size; + + /* continue building the right side */ + if (! _smk_huff16_build_rec(t, bs, low8, hi8, limit)) { + fputs("libsmacker::_smk_huff16_build_rec() - ERROR: failed to build right sub-tree\n", stderr); + return 0; + } + } else { + /* Bit unset signifies a Leaf node. */ + /* Attempt to read LOW value */ + if ((value = smk_huff8_lookup(low8, bs)) < 0) { + fputs("libsmacker::_smk_huff16_build_rec() - ERROR: get LOW value returned -1\n", stderr); + return 0; + } + + t->tree[t->size] = value; + + /* now read HIGH value */ + if ((value = smk_huff8_lookup(hi8, bs)) < 0) { + fputs("libsmacker::_smk_huff16_build_rec() - ERROR: get HIGH value returned -1\n", stderr); + return 0; + } + + /* Looks OK: we got low and hi values. Return a new LEAF */ + t->tree[t->size] |= (value << 8); + + /* Last: when building the tree, some Values may correspond to cache positions. + Identify these values and set the Escape code byte accordingly. */ + if (t->tree[t->size] == t->cache[0]) + t->tree[t->size] = SMK_HUFF16_CACHE; + else if (t->tree[t->size] == t->cache[1]) + t->tree[t->size] = SMK_HUFF16_CACHE | 1; + else if (t->tree[t->size] == t->cache[2]) + t->tree[t->size] = SMK_HUFF16_CACHE | 2; + + t->size ++; + } + + return 1; +} + +/* Entry point for building a big 16-bit tree. */ +static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * const bs, const unsigned int alloc_size) +{ + struct smk_huff8_t low8, hi8; + size_t limit; + int value, i, bit; + /* null check */ + assert(t); + assert(bs); + + /* Smacker huff trees begin with a set-bit. */ + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::smk_huff16_build() - ERROR: initial get_bit returned -1\n", stderr); + return 0; + } + + t->size = 0; + + /* First bit indicates whether a tree is present or not. */ + /* Very small or audio-only files may have no tree. */ + if (bit) { + /* build low-8-bits tree */ + if (! smk_huff8_build(&low8, bs)) { + fputs("libsmacker::smk_huff16_build() - ERROR: failed to build LOW tree\n", stderr); + return 0; + } + + /* build hi-8-bits tree */ + if (! smk_huff8_build(&hi8, bs)) { + fputs("libsmacker::smk_huff16_build() - ERROR: failed to build HIGH tree\n", stderr); + return 0; + } + + /* Init the escape code cache. */ + for (i = 0; i < 3; i ++) { + if ((value = smk_bs_read_8(bs)) < 0) { + fprintf(stderr, "libsmacker::smk_huff16_build() - ERROR: get LOW value for cache %d returned -1\n", i); + return 0; + } + + t->cache[i] = value; + + /* now read HIGH value */ + if ((value = smk_bs_read_8(bs)) < 0) { + fprintf(stderr, "libsmacker::smk_huff16_build() - ERROR: get HIGH value for cache %d returned -1\n", i); + return 0; + } + + t->cache[i] |= (value << 8); + } + + /* Everything looks OK so far. Time to malloc structure. */ + if (alloc_size < 12 || alloc_size % 4) { + fprintf(stderr, "libsmacker::smk_huff16_build() - ERROR: illegal value %u for alloc_size\n", alloc_size); + return 0; + } + + limit = (alloc_size - 12) / 4; + + if ((t->tree = malloc(limit * sizeof(unsigned int))) == NULL) { + perror("libsmacker::smk_huff16_build() - ERROR: failed to malloc() huff16 tree"); + return 0; + } + + /* Finally, call recursive function to retrieve the Bigtree. */ + if (! _smk_huff16_build_rec(t, bs, &low8, &hi8, limit)) { + fputs("libsmacker::smk_huff16_build() - ERROR: failed to build huff16 tree\n", stderr); + free(t->tree); + t->tree = NULL; + return 0; + } -/* GLOBALS */ + /* check that we completely filled the tree */ + if (limit != t->size) { + fputs("libsmacker::smk_huff16_build() - ERROR: failed to completely decode huff16 tree\n", stderr); + free(t->tree); + t->tree = NULL; + return 0; + } + } else { + if ((t->tree = malloc(sizeof(unsigned int))) == NULL) { + perror("libsmacker::smk_huff16_build() - ERROR: failed to malloc() huff16 tree"); + return 0; + } + + t->tree[0] = 0; + //t->cache[0] = t->cache[1] = t->cache[2] = 0; + } + + /* Check final end tag. */ + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::smk_huff16_build() - ERROR: final get_bit returned -1\n", stderr); + free(t->tree); + t->tree = NULL; + return 0; + } + + /* a 0 is expected here, a 1 generally indicates a problem! */ + if (bit) { + fputs("libsmacker::smk_huff16_build() - ERROR: final get_bit returned 1\n", stderr); + free(t->tree); + t->tree = NULL; + return 0; + } + + return 1; +} + +/* Look up a 16-bit value from a large huff tree. + Return -1 on error. + Note that this also updates the recently-used-values cache. */ +static int smk_huff16_lookup(struct smk_huff16_t * const t, struct smk_bit_t * const bs) +{ + int bit, value, index = 0; + /* null check */ + assert(t); + assert(bs); + + while (t->tree[index] & SMK_HUFF16_BRANCH) { + if ((bit = smk_bs_read_1(bs)) < 0) { + fputs("libsmacker::smk_huff16_lookup() - ERROR: get_bit returned -1\n", stderr); + return -1; + } + + if (bit) { + /* take the right branch */ + index = t->tree[index] & SMK_HUFF16_LEAF_MASK; + } else { + /* take the left branch */ + index ++; + } + } + + /* Get the value at this point */ + value = t->tree[index]; + + if (value & SMK_HUFF16_CACHE) { + /* uses cached value instead of actual value */ + value = t->cache[value & SMK_HUFF16_LEAF_MASK]; + } + + if (t->cache[0] != value) { + /* Update the cache, by moving val to the front of the queue, + if it isn't already there. */ + t->cache[2] = t->cache[1]; + t->cache[1] = t->cache[0]; + t->cache[0] = value; + } + + return value; +} + +/* ************************************************************************* */ +/* SMACKER Structure */ +/* ************************************************************************* */ /* tree processing order */ #define SMK_TREE_MMAP 0 #define SMK_TREE_MCLR 1 #define SMK_TREE_FULL 2 #define SMK_TREE_TYPE 3 -/* SMACKER DATA STRUCTURES */ -struct smk_t -{ +struct smk_t { /* meta-info */ /* file mode: see flags, smacker.h */ unsigned char mode; @@ -47,33 +515,30 @@ struct smk_t /* SOURCE union. Where the data is going to be read from (or be stored), depending on the file mode. */ - union - { - struct - { + union { + struct { /* on-disk mode */ - FILE* fp; - unsigned long* chunk_offset; + FILE * fp; + unsigned long * chunk_offset; } file; /* in-memory mode: unprocessed chunks */ - unsigned char** chunk_data; + unsigned char ** chunk_data; } source; /* shared array of "chunk sizes"*/ - unsigned long* chunk_size; + unsigned long * chunk_size; /* Holds per-frame flags (i.e. 'keyframe') */ - unsigned char* keyframe; + unsigned char * keyframe; /* Holds per-frame type mask (e.g. 'audio track 3, 2, and palette swap') */ - unsigned char* frame_type; + unsigned char * frame_type; /* video and audio structures */ /* Video data type: enable/disable decode switch, video info and flags, pointer to last-decoded-palette */ - struct smk_video_t - { + struct smk_video_t { /* enable/disable decode switch */ unsigned char enable; @@ -90,18 +555,17 @@ struct smk_t unsigned char v; /* Huffman trees */ - /* unsigned long tree_size[4]; */ - struct smk_huff16_t* tree[4]; + unsigned long tree_size[4]; + struct smk_huff16_t tree[4]; /* Palette data type: pointer to last-decoded-palette */ unsigned char palette[256][3]; /* Last-unpacked frame */ - unsigned char* frame; + unsigned char * frame; } video; /* audio structure */ - struct smk_audio_t - { + struct smk_audio_t { /* set if track exists in file */ unsigned char exists; @@ -121,41 +585,45 @@ struct smk_t unsigned char compress; /* pointer to last-decoded-audio-buffer */ - void* buffer; + void * buffer; unsigned long buffer_size; } audio[7]; }; -union smk_read_t -{ - FILE* file; - unsigned char* ram; +union smk_read_t { + FILE * file; + unsigned char * ram; }; +/* ************************************************************************* */ +/* SMACKER Functions */ +/* ************************************************************************* */ /* An fread wrapper: consumes N bytes, or returns -1 on failure (when size doesn't match expected) */ -static char smk_read_file(void* buf, const size_t size, FILE* fp) +static char smk_read_file(void * buf, const size_t size, FILE * fp) { /* don't bother checking buf or fp, fread does it for us */ - size_t bytesRead = fread(buf,1,size,fp); - if (bytesRead != size) - { - fprintf(stderr, "libsmacker::smk_read_file(buf,%lu,fp) - ERROR: Short read, %lu bytes returned\n\tReason: %s\n", (unsigned long)size, (unsigned long)bytesRead, strerror(errno)); + size_t bytesRead = fread(buf, 1, size, fp); + + if (bytesRead != size) { + fprintf(stderr, "libsmacker::smk_read_file(buf,%lu,fp) - ERROR: Short read, %lu bytes returned\n", (unsigned long)size, (unsigned long)bytesRead); + perror("\tReason"); return -1; } + return 0; } /* A memcpy wrapper: consumes N bytes, or returns -1 on failure (when size too low) */ -static char smk_read_memory(void* buf, const unsigned long size, unsigned char** p, unsigned long* p_size) +static char smk_read_memory(void * buf, const unsigned long size, unsigned char ** p, unsigned long * p_size) { - if (size > *p_size) - { - fprintf(stderr,"libsmacker::smk_read_memory(buf,%lu,p,%lu) - ERROR: Short read\n",(unsigned long)size, (unsigned long)*p_size); + if (size > *p_size) { + fprintf(stderr, "libsmacker::smk_read_memory(buf,%lu,p,%lu) - ERROR: Short read\n", (unsigned long)size, (unsigned long)*p_size); return -1; } - memcpy(buf,*p,size); + + memcpy(buf, *p, size); *p += size; *p_size -= size; return 0; @@ -195,68 +663,66 @@ static char smk_read_memory(void* buf, const unsigned long size, unsigned char** /* open an smk (from a generic Source) */ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned long size, const unsigned char process_mode) { - smk s = NULL; - + /* Smacker structure we intend to work on / return */ + smk s; /* Temporary variables */ long temp_l; unsigned long temp_u; - /* r is used by macros above for return code */ char r; unsigned char buf[4] = {'\0'}; - /* video hufftrees are stored as a large chunk (bitstream) these vars are used to load, then decode them */ - unsigned char* hufftree_chunk = NULL; + unsigned char * hufftree_chunk = NULL; unsigned long tree_size; /* a bitstream struct */ - struct smk_bit_t* bs = NULL; + struct smk_bit_t bs; + /** **/ /* safe malloc the structure */ - smk_malloc(s,sizeof (struct smk_t)); + if ((s = calloc(1, sizeof(struct smk_t))) == NULL) { + perror("libsmacker::smk_open_generic() - ERROR: failed to malloc() smk structure"); + return NULL; + } /* Check for a valid signature */ - smk_read(buf,3); - if (buf[0] != 'S' || buf[1] != 'M' || buf[2] != 'K') - { - fprintf(stderr,"libsmacker::smk_open_generic - ERROR: invalid SMKn signature (got: %s)\n",buf); + smk_read(buf, 3); + + if (buf[0] != 'S' || buf[1] != 'M' || buf[2] != 'K') { + fprintf(stderr, "libsmacker::smk_open_generic - ERROR: invalid SMKn signature (got: %s)\n", buf); goto error; } /* Read .smk file version */ - smk_read(&s->video.v,1); - if (s->video.v != '2' && s->video.v != '4') - { - fprintf(stderr,"libsmacker::smk_open_generic - Warning: invalid SMK version %c (expected: 2 or 4)\n",s->video.v); + smk_read(&s->video.v, 1); + + if (s->video.v != '2' && s->video.v != '4') { + fprintf(stderr, "libsmacker::smk_open_generic - Warning: invalid SMK version %c (expected: 2 or 4)\n", s->video.v); + /* take a guess */ if (s->video.v < '4') s->video.v = '2'; else s->video.v = '4'; - fprintf(stderr,"\tProcessing will continue as type %c\n",s->video.v); + + fprintf(stderr, "\tProcessing will continue as type %c\n", s->video.v); } /* width, height, total num frames */ smk_read_ul(s->video.w); smk_read_ul(s->video.h); - smk_read_ul(s->f); - /* frames per second calculation */ smk_read_ul(temp_u); temp_l = (int)temp_u; - if (temp_l > 0) - { + + if (temp_l > 0) { /* millisec per frame */ s->usf = temp_l * 1000; - } - else if (temp_l < 0) - { + } else if (temp_l < 0) { /* 10 microsec per frame */ s->usf = temp_l * -10; - } - else - { + } else { /* defaults to 10 usf (= 100000 microseconds) */ s->usf = 100000; } @@ -266,63 +732,52 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned Y scale / Y interlace go in the Video flags. The user should scale appropriately. */ smk_read_ul(temp_u); + if (temp_u & 0x01) - { s->ring_frame = 1; - } + if (temp_u & 0x02) - { s->video.y_scale_mode = SMK_FLAG_Y_DOUBLE; - } - if (temp_u & 0x04) - { + + if (temp_u & 0x04) { if (s->video.y_scale_mode == SMK_FLAG_Y_DOUBLE) - { - fputs("libsmacker::smk_open_generic - Warning: SMK file specifies both Y-Double AND Y-Interlace.\n",stderr); - } + fputs("libsmacker::smk_open_generic - Warning: SMK file specifies both Y-Double AND Y-Interlace.\n", stderr); + s->video.y_scale_mode = SMK_FLAG_Y_INTERLACE; } /* Max buffer size for each audio track - used to pre-allocate buffers */ for (temp_l = 0; temp_l < 7; temp_l ++) - { smk_read_ul(s->audio[temp_l].max_buffer); - } /* Read size of "hufftree chunk" - save for later. */ smk_read_ul(tree_size); - /* "unpacked" sizes of each huff tree - we don't use - but calling application might. */ + /* "unpacked" sizes of each huff tree */ for (temp_l = 0; temp_l < 4; temp_l ++) - { -/* smk_read_ul(s->video.tree_size[temp_u]); */ - smk_read_ul(temp_u); - } + smk_read_ul(s->video.tree_size[temp_l]); /* read audio rate data */ - for (temp_l = 0; temp_l < 7; temp_l ++) - { + for (temp_l = 0; temp_l < 7; temp_l ++) { smk_read_ul(temp_u); - if (temp_u & 0x40000000) - { + + if (temp_u & 0x40000000) { /* Audio track specifies "exists" flag, malloc structure and copy components. */ s->audio[temp_l].exists = 1; - /* and for all audio tracks */ smk_malloc(s->audio[temp_l].buffer, s->audio[temp_l].max_buffer); if (temp_u & 0x80000000) - { s->audio[temp_l].compress = 1; - } + s->audio[temp_l].bitdepth = ((temp_u & 0x20000000) ? 16 : 8); s->audio[temp_l].channels = ((temp_u & 0x10000000) ? 2 : 1); - if (temp_u & 0x0c000000) - { - fprintf(stderr,"libsmacker::smk_open_generic - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n",temp_l); + + if (temp_u & 0x0c000000) { + fprintf(stderr, "libsmacker::smk_open_generic - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n", temp_l); s->audio[temp_l].compress = 2; } + /* Bits 25 & 24 are unused. */ s->audio[temp_l].rate = (temp_u & 0x00FFFFFF); } @@ -330,140 +785,126 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned /* Skip over Dummy field */ smk_read_ul(temp_u); - /* FrameSizes and Keyframe marker are stored together. */ - smk_malloc(s->keyframe,(s->f + s->ring_frame)); - smk_malloc(s->chunk_size,(s->f + s->ring_frame) * sizeof(unsigned long)); + smk_malloc(s->keyframe, (s->f + s->ring_frame)); + smk_malloc(s->chunk_size, (s->f + s->ring_frame) * sizeof(unsigned long)); - for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) - { + for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) { smk_read_ul(s->chunk_size[temp_u]); /* Set Keyframe */ if (s->chunk_size[temp_u] & 0x01) - { s->keyframe[temp_u] = 1; - } + /* Bits 1 is used, but the purpose is unknown. */ s->chunk_size[temp_u] &= 0xFFFFFFFC; } /* That was easy... Now read FrameTypes! */ - smk_malloc(s->frame_type,(s->f + s->ring_frame)); + smk_malloc(s->frame_type, (s->f + s->ring_frame)); + for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) - { - smk_read(&s->frame_type[temp_u],1); - } + smk_read(&s->frame_type[temp_u], 1); /* HuffmanTrees We know the sizes already: read and assemble into something actually parse-able at run-time */ - smk_malloc(hufftree_chunk,tree_size); - smk_read(hufftree_chunk,tree_size); - + smk_malloc(hufftree_chunk, tree_size); + smk_read(hufftree_chunk, tree_size); /* set up a Bitstream */ - bs = smk_bs_init(hufftree_chunk, tree_size); + smk_bs_init(&bs, hufftree_chunk, tree_size); + /* create some tables */ - for (temp_u = 0; temp_u < 4; temp_u ++) - { - smk_huff16_build(bs,s->video.tree[temp_u]); + for (temp_u = 0; temp_u < 4; temp_u ++) { + if (! smk_huff16_build(&s->video.tree[temp_u], &bs, s->video.tree_size[temp_u])) { + fprintf(stderr, "libsmacker::smk_open_generic - ERROR: failed to create huff16 tree %lu\n", temp_u); + goto error; + } } /* clean up */ - smk_free(bs); smk_free(hufftree_chunk); - /* Go ahead and malloc storage for the video frame */ - smk_malloc(s->video.frame,s->video.w * s->video.h); - + smk_malloc(s->video.frame, s->video.w * s->video.h); /* final processing: depending on ProcessMode, handle what to do with rest of file data */ s->mode = process_mode; /* Handle the rest of the data. For MODE_MEMORY, read the chunks and store */ - if (s->mode == SMK_MODE_MEMORY) - { - smk_malloc(s->source.chunk_data,(s->f + s->ring_frame) * sizeof(unsigned char*)); - for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) - { - smk_malloc(s->source.chunk_data[temp_u],s->chunk_size[temp_u]); - smk_read(s->source.chunk_data[temp_u],s->chunk_size[temp_u]); + if (s->mode == SMK_MODE_MEMORY) { + smk_malloc(s->source.chunk_data, (s->f + s->ring_frame) * sizeof(unsigned char *)); + + for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) { + smk_malloc(s->source.chunk_data[temp_u], s->chunk_size[temp_u]); + smk_read(s->source.chunk_data[temp_u], s->chunk_size[temp_u]); } - } - else - { + } else { /* MODE_STREAM: don't read anything now, just precompute offsets. use fseek to verify that the file is "complete" */ - smk_malloc(s->source.file.chunk_offset,(s->f + s->ring_frame) * sizeof(unsigned long)); - for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) - { + smk_malloc(s->source.file.chunk_offset, (s->f + s->ring_frame) * sizeof(unsigned long)); + + for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) { s->source.file.chunk_offset[temp_u] = ftell(fp.file); - if (fseek(fp.file,s->chunk_size[temp_u],SEEK_CUR)) - { - fprintf(stderr,"libsmacker::smk_open - ERROR: fseek to frame %lu not OK.\n",temp_u); - perror ("\tError reported was"); + + if (fseek(fp.file, s->chunk_size[temp_u], SEEK_CUR)) { + fprintf(stderr, "libsmacker::smk_open - ERROR: fseek to frame %lu not OK.\n", temp_u); + perror("\tError reported was"); goto error; } } } return s; - error: - smk_free(bs); smk_free(hufftree_chunk); smk_close(s); return NULL; } /* open an smk (from a memory buffer) */ -smk smk_open_memory(const unsigned char* buffer, const unsigned long size) +smk smk_open_memory(const unsigned char * buffer, const unsigned long size) { smk s = NULL; - union smk_read_t fp; - smk_assert(buffer); + if (buffer == NULL) { + fputs("libsmacker::smk_open_memory() - ERROR: buffer pointer is NULL\n", stderr); + return NULL; + } /* set up the read union for Memory mode */ - fp.ram = (unsigned char*)buffer; + fp.ram = (unsigned char *)buffer; - if (!(s = smk_open_generic(0,fp,size,SMK_MODE_MEMORY))) - { - fprintf(stderr,"libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n",size); - } + if (!(s = smk_open_generic(0, fp, size, SMK_MODE_MEMORY))) + fprintf(stderr, "libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", size); - /* fall through, return s or null */ -error: return s; } /* open an smk (from a file) */ -smk smk_open_filepointer(FILE* file, const unsigned char mode) +smk smk_open_filepointer(FILE * file, const unsigned char mode) { smk s = NULL; union smk_read_t fp; - smk_assert(file); + if (file == NULL) { + fputs("libsmacker::smk_open_filepointer() - ERROR: file pointer is NULL\n", stderr); + return NULL; + } /* Copy file ptr to internal union */ fp.file = file; - if (!(s = smk_open_generic(1,fp,0,mode))) - { - fprintf(stderr,"libsmacker::smk_open_filepointer(file,%u) - ERROR: Fatal error in smk_open_generic, returning NULL.\n",mode); + if (!(s = smk_open_generic(1, fp, 0, mode))) { + fprintf(stderr, "libsmacker::smk_open_filepointer(file,%u) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", mode); fclose(fp.file); goto error; } if (mode == SMK_MODE_MEMORY) - { fclose(fp.file); - } else - { s->source.file.fp = fp.file; - } /* fall through, return s or null */ error: @@ -471,22 +912,23 @@ error: } /* open an smk (from a file) */ -smk smk_open_file(const char* filename, const unsigned char mode) +smk smk_open_file(const char * filename, const unsigned char mode) { - FILE* fp; + FILE * fp; - smk_assert(filename); + if (filename == NULL) { + fputs("libsmacker::smk_open_file() - ERROR: filename is NULL\n", stderr); + return NULL; + } - if (!(fp = fopen(filename,"rb"))) - { - fprintf(stderr,"libsmacker::smk_open_file(%s,%u) - ERROR: could not open file (errno: %d)\n",filename,mode,errno); - perror ("\tError reported was"); + if (!(fp = fopen(filename, "rb"))) { + fprintf(stderr, "libsmacker::smk_open_file(%s,%u) - ERROR: could not open file\n", filename, mode); + perror("\tError reported was"); goto error; } /* kick processing to smk_open_filepointer */ - return smk_open_filepointer(fp,mode); - + return smk_open_filepointer(fp, mode); /* fall through, return s or null */ error: return NULL; @@ -497,63 +939,61 @@ void smk_close(smk s) { unsigned long u; - smk_assert(s); + if (s == NULL) { + fputs("libsmacker::smk_close() - ERROR: smk is NULL\n", stderr); + return; + } /* free video sub-components */ - { - for (u = 0; u < 4; u ++) - { - if (s->video.tree[u]) smk_huff16_free(s->video.tree[u]); - } - smk_free(s->video.frame); + for (u = 0; u < 4; u ++) { + if (s->video.tree[u].tree) free(s->video.tree[u].tree); } + smk_free(s->video.frame); + /* free audio sub-components */ - for (u=0; u<7; u++) - { - smk_free(s->audio[u].buffer); + for (u = 0; u < 7; u++) { + if (s->audio[u].buffer) + smk_free(s->audio[u].buffer); } smk_free(s->keyframe); smk_free(s->frame_type); - if (s->mode == SMK_MODE_DISK) - { + if (s->mode == SMK_MODE_DISK) { /* disk-mode */ if (s->source.file.fp) - { fclose(s->source.file.fp); - } + smk_free(s->source.file.chunk_offset); - } - else - { + } else { /* mem-mode */ - if (s->source.chunk_data != NULL) - { - for (u=0; u<(s->f + s->ring_frame); u++) - { + if (s->source.chunk_data != NULL) { + for (u = 0; u < (s->f + s->ring_frame); u++) smk_free(s->source.chunk_data[u]); - } + smk_free(s->source.chunk_data); } } - smk_free(s->chunk_size); + smk_free(s->chunk_size); smk_free(s); - -error: ; } /* tell some info about the file */ -char smk_info_all(const smk object, unsigned long* frame, unsigned long* frame_count, double* usf) +char smk_info_all(const smk object, unsigned long * frame, unsigned long * frame_count, double * usf) { - /* sanity check */ - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_info_all() - ERROR: smk is NULL\n", stderr); + return -1; + } + if (!frame && !frame_count && !usf) { - fputs("libsmacker::smk_info_all(object,frame,frame_count,usf) - ERROR: Request for info with all-NULL return references\n",stderr); + fputs("libsmacker::smk_info_all(object,frame,frame_count,usf) - ERROR: Request for info with all-NULL return references\n", stderr); goto error; } + if (frame) *frame = (object->cur_frame % object->f); @@ -564,18 +1004,20 @@ char smk_info_all(const smk object, unsigned long* frame, unsigned long* frame_c *usf = object->usf; return 0; - error: return -1; } -char smk_info_video(const smk object, unsigned long* w, unsigned long* h, unsigned char* y_scale_mode) +char smk_info_video(const smk object, unsigned long * w, unsigned long * h, unsigned char * y_scale_mode) { - /* sanity check */ - smk_assert(object); - if (!w && !h && !y_scale_mode) - { - fputs("libsmacker::smk_info_all(object,w,h,y_scale_mode) - ERROR: Request for info with all-NULL return references\n",stderr); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_info_video() - ERROR: smk is NULL\n", stderr); + return -1; + } + + if (!w && !h && !y_scale_mode) { + fputs("libsmacker::smk_info_all(object,w,h,y_scale_mode) - ERROR: Request for info with all-NULL return references\n", stderr); return -1; } @@ -589,58 +1031,49 @@ char smk_info_video(const smk object, unsigned long* w, unsigned long* h, unsign *y_scale_mode = object->video.y_scale_mode; return 0; - -error: - return -1; } -char smk_info_audio(const smk object, unsigned char* track_mask, unsigned char channels[7], unsigned char bitdepth[7], unsigned long audio_rate[7]) +char smk_info_audio(const smk object, unsigned char * track_mask, unsigned char channels[7], unsigned char bitdepth[7], unsigned long audio_rate[7]) { unsigned char i; - /* sanity check */ - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_info_audio() - ERROR: smk is NULL\n", stderr); + return -1; + } - if (!track_mask && !channels && !bitdepth && !audio_rate) - { - fputs("libsmacker::smk_info_audio(object,track_mask,channels,bitdepth,audio_rate) - ERROR: Request for info with all-NULL return references\n",stderr); + if (!track_mask && !channels && !bitdepth && !audio_rate) { + fputs("libsmacker::smk_info_audio(object,track_mask,channels,bitdepth,audio_rate) - ERROR: Request for info with all-NULL return references\n", stderr); return -1; } - if (track_mask) - { - *track_mask = ( (object->audio[0].exists) | - ( (object->audio[1].exists) << 1 ) | - ( (object->audio[2].exists) << 2 ) | - ( (object->audio[3].exists) << 3 ) | - ( (object->audio[4].exists) << 4 ) | - ( (object->audio[5].exists) << 5 ) | - ( (object->audio[6].exists) << 6 ) ); - } - if (channels) - { + + if (track_mask) { + *track_mask = ((object->audio[0].exists) | + ((object->audio[1].exists) << 1) | + ((object->audio[2].exists) << 2) | + ((object->audio[3].exists) << 3) | + ((object->audio[4].exists) << 4) | + ((object->audio[5].exists) << 5) | + ((object->audio[6].exists) << 6)); + } + + if (channels) { for (i = 0; i < 7; i ++) - { channels[i] = object->audio[i].channels; - } } - if (bitdepth) - { + + if (bitdepth) { for (i = 0; i < 7; i ++) - { bitdepth[i] = object->audio[i].bitdepth; - } } - if (audio_rate) - { + + if (audio_rate) { for (i = 0; i < 7; i ++) - { audio_rate[i] = object->audio[i].rate; - } } - return 0; -error: - return -1; + return 0; } /* Enable-disable switches */ @@ -648,100 +1081,98 @@ char smk_enable_all(smk object, const unsigned char mask) { unsigned char i; - /* sanity check */ - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_enable_all() - ERROR: smk is NULL\n", stderr); + return -1; + } /* set video-enable */ object->video.enable = (mask & 0x80); - for (i = 0; i < 7; i ++) - { + for (i = 0; i < 7; i ++) { if (object->audio[i].exists) - { object->audio[i].enable = (mask & (1 << i)); - } } return 0; - -error: - return -1; } char smk_enable_video(smk object, const unsigned char enable) { - /* sanity check */ - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_enable_video() - ERROR: smk is NULL\n", stderr); + return -1; + } object->video.enable = enable; return 0; - -error: - return -1; } char smk_enable_audio(smk object, const unsigned char track, const unsigned char enable) { - /* sanity check */ - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_enable_audio() - ERROR: smk is NULL\n", stderr); + return -1; + } object->audio[track].enable = enable; return 0; - -error: - return -1; } -const unsigned char* smk_get_palette(const smk object) +const unsigned char * smk_get_palette(const smk object) { - smk_assert(object); - - return (unsigned char*)object->video.palette; + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_get_palette() - ERROR: smk is NULL\n", stderr); + return NULL; + } -error: - return NULL; + return (unsigned char *)object->video.palette; } -const unsigned char* smk_get_video(const smk object) +const unsigned char * smk_get_video(const smk object) { - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_get_video() - ERROR: smk is NULL\n", stderr); + return NULL; + } return object->video.frame; - -error: - return NULL; } -const unsigned char* smk_get_audio(const smk object, const unsigned char t) +const unsigned char * smk_get_audio(const smk object, const unsigned char t) { - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_get_audio() - ERROR: smk is NULL\n", stderr); + return NULL; + } return object->audio[t].buffer; - -error: - return NULL; } unsigned long smk_get_audio_size(const smk object, const unsigned char t) { - smk_assert(object); + /* null check */ + if (object == NULL) { + fputs("libsmacker::smk_get_audio_size() - ERROR: smk is NULL\n", stderr); + return 0; + } return object->audio[t].buffer_size; - -error: - return 0; } /* Decompresses a palette-frame. */ -static char smk_render_palette(struct smk_video_t* s, unsigned char* p, unsigned long size) +static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsigned long size) { /* Index into palette */ unsigned short i = 0; /* Helper variables */ unsigned short count, src; - static unsigned char oldPalette[256][3]; - /* Smacker palette map: smk colors are 6-bit, this table expands them to 8. */ - const unsigned char palmap[64] = - { + const unsigned char palmap[64] = { 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D, @@ -751,123 +1182,108 @@ static char smk_render_palette(struct smk_video_t* s, unsigned char* p, unsigned 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF, 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF }; - - /* sanity check */ - smk_assert(s); - smk_assert(p); - - // Copy palette to old palette + /* null check */ + assert(s); + assert(p); + /* Copy palette to old palette */ memcpy(oldPalette, s->palette, 256 * 3); /* Loop until palette is complete, or we are out of bytes to process */ - while ( (i < 256) && (size > 0) ) - { - if ((*p) & 0x80) - { + while ((i < 256) && (size > 0)) { + if ((*p) & 0x80) { /* 0x80: Skip block (preserve C+1 palette entries from previous palette) */ count = ((*p) & 0x7F) + 1; - p ++; size --; + p ++; + size --; /* check for overflow condition */ - if (i + count > 256) - { - fprintf(stderr,"libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x80 attempt to skip %d entries from %d\n",count,i); + if (i + count > 256) { + fprintf(stderr, "libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x80 attempt to skip %d entries from %d\n", count, i); goto error; } /* finally: advance the index. */ i += count; - } - else if ((*p) & 0x40) - { + } else if ((*p) & 0x40) { /* 0x40: Color-shift block Copy (c + 1) color entries of the previous palette, starting from entry (s), to the next entries of the new palette. */ - if (size < 2) - { - fputs("libsmacker::palette_render(s,p,size) - ERROR: 0x40 ran out of bytes for copy\n",stderr); + if (size < 2) { + fputs("libsmacker::palette_render(s,p,size) - ERROR: 0x40 ran out of bytes for copy\n", stderr); goto error; } /* pick "count" items to copy */ count = ((*p) & 0x3F) + 1; - p ++; size --; - + p ++; + size --; /* start offset of old palette */ src = *p; - p ++; size --; + p ++; + size --; /* overflow: see if we write/read beyond 256colors, or overwrite own palette */ - if (i + count > 256 || src + count > 256) - { - fprintf(stderr,"libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x40 attempt to copy %d entries from %d to %d\n",count,src,i); + if (i + count > 256 || src + count > 256 || + (src < i && src + count > i)) { + fprintf(stderr, "libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x40 attempt to copy %d entries from %d to %d\n", count, src, i); goto error; } /* OK! Copy the color-palette entries. */ - memmove(&s->palette[i][0],&oldPalette[src][0],count * 3); - + memmove(&s->palette[i][0], &oldPalette[src][0], count * 3); i += count; - } - else - { + } else { /* 0x00: Set Color block Direct-set the next 3 bytes for palette index */ - if (size < 3) - { - fprintf(stderr,"libsmacker::palette_render - ERROR: 0x3F ran out of bytes for copy, size=%lu\n", size); + if (size < 3) { + fprintf(stderr, "libsmacker::palette_render - ERROR: 0x3F ran out of bytes for copy, size=%lu\n", size); goto error; } - for (count = 0; count < 3; count ++) - { - if (*p > 0x3F) - { - fprintf(stderr,"libsmacker::palette_render - ERROR: palette index exceeds 0x3F (entry [%u][%u])\n", i, count); + for (count = 0; count < 3; count ++) { + if (*p > 0x3F) { + fprintf(stderr, "libsmacker::palette_render - ERROR: palette index exceeds 0x3F (entry [%u][%u])\n", i, count); goto error; } + s->palette[i][count] = palmap[*p]; - p++; size --; + p++; + size --; } + i ++; } } - if (i < 256) - { - fprintf(stderr,"libsmacker::palette_render - ERROR: did not completely fill palette (idx=%u)\n",i); + if (i < 256) { + fprintf(stderr, "libsmacker::palette_render - ERROR: did not completely fill palette (idx=%u)\n", i); goto error; } return 0; - error: /* Error, return -1 The new palette probably has errors but is preferrable to a black screen */ return -1; } -static char smk_render_video(struct smk_video_t* s, unsigned char* p, unsigned int size) +static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned int size) { - unsigned char* t = s->frame; - unsigned char s1,s2; + unsigned char * t = s->frame; + unsigned char s1, s2; unsigned short temp; - unsigned long i,j,k, row, col,skip; - + unsigned long i, j, k, row, col, skip; /* used for video decoding */ - struct smk_bit_t* bs = NULL; - + struct smk_bit_t bs; /* results from a tree lookup */ - long unpack; - + int unpack; /* unpack, broken into pieces */ unsigned char type; unsigned char blocklen; unsigned char typedata; char bit; - const unsigned short sizetable[64] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, @@ -878,335 +1294,305 @@ static char smk_render_video(struct smk_video_t* s, unsigned char* p, unsigned i 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 128, 256, 512, 1024, 2048 }; - - /* sanity check */ - smk_assert(s); - smk_assert(p); - + /* null check */ + assert(s); + assert(p); row = 0; col = 0; - /* Set up a bitstream for video unpacking */ - /* We could check the return code but it will only fail if p is null and we already verified that. */ - bs = smk_bs_init (p, size); + smk_bs_init(&bs, p, size); /* Reset the cache on all bigtrees */ - smk_huff16_reset(s->tree[0]); - smk_huff16_reset(s->tree[1]); - smk_huff16_reset(s->tree[2]); - smk_huff16_reset(s->tree[3]); + for (i = 0; i < 4; i++) + memset(&s->tree[i].cache, 0, 3 * sizeof(unsigned short)); - while ( row < s->h ) - { - smk_huff16_lookup(bs,s->tree[SMK_TREE_TYPE],unpack); + while (row < s->h) { + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_TYPE], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from TYPE tree.\n", stderr); + return -1; + } type = ((unpack & 0x0003)); blocklen = ((unpack & 0x00FC) >> 2); typedata = ((unpack & 0xFF00) >> 8); /* support for v4 full-blocks */ - if (type == 1 && s->v == '4') - { - smk_bs_read_1(bs, bit); + if (type == 1 && s->v == '4') { + bit = smk_bs_read_1(&bs); + if (bit) - { type = 4; - } else { - smk_bs_read_1(bs, bit); + else { + bit = smk_bs_read_1(&bs); + if (bit) - { type = 5; - } } } - for (j = 0; (j < sizetable[blocklen]) && (row < s->h); j ++) - { + for (j = 0; (j < sizetable[blocklen]) && (row < s->h); j ++) { skip = (row * s->w) + col; - switch(type) - { - case 0: - smk_huff16_lookup(bs,s->tree[SMK_TREE_MCLR],unpack); - s1 = (unpack & 0xFF00) >> 8; - s2 = (unpack & 0x00FF); - smk_huff16_lookup(bs,s->tree[SMK_TREE_MMAP],unpack); - - temp = 0x01; - for (k = 0; k < 4; k ++) - { - for (i = 0; i < 4; i ++) - { - if (unpack & temp) - { - t[skip + i] = s1; - } - else - { - t[skip + i] = s2; - } - temp = temp << 1; - } - skip += s->w; + + switch (type) { + case 0: + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_MCLR], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from MCLR tree.\n", stderr); + return -1; + } + + s1 = (unpack & 0xFF00) >> 8; + s2 = (unpack & 0x00FF); + + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_MMAP], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from MMAP tree.\n", stderr); + return -1; + } + + temp = 0x01; + + for (k = 0; k < 4; k ++) { + for (i = 0; i < 4; i ++) { + if (unpack & temp) + t[skip + i] = s1; + else + t[skip + i] = s2; + + temp = temp << 1; } - break; - - case 1: /* FULL BLOCK */ - for (k = 0; k < 4; k ++) - { - smk_huff16_lookup(bs,s->tree[SMK_TREE_FULL],unpack); - t[skip + 3] = ((unpack & 0xFF00) >> 8); - t[skip + 2] = (unpack & 0x00FF); - smk_huff16_lookup(bs,s->tree[SMK_TREE_FULL],unpack); - t[skip + 1] = ((unpack & 0xFF00) >> 8); - t[skip] = (unpack & 0x00FF); - skip += s->w; + + skip += s->w; + } + + break; + + case 1: /* FULL BLOCK */ + for (k = 0; k < 4; k ++) { + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n", stderr); + return -1; } - break; - case 2: /* VOID BLOCK */ - /* break; - if (s->frame) - { - memcpy(&t[skip], &s->frame[skip], 4); - skip += s->w; - memcpy(&t[skip], &s->frame[skip], 4); - skip += s->w; - memcpy(&t[skip], &s->frame[skip], 4); - skip += s->w; - memcpy(&t[skip], &s->frame[skip], 4); - } */ - break; - case 3: /* SOLID BLOCK */ - memset(&t[skip],typedata,4); + + t[skip + 3] = ((unpack & 0xFF00) >> 8); + t[skip + 2] = (unpack & 0x00FF); + + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n", stderr); + return -1; + } + + t[skip + 1] = ((unpack & 0xFF00) >> 8); + t[skip] = (unpack & 0x00FF); skip += s->w; - memset(&t[skip],typedata,4); + } + + break; + + case 2: /* VOID BLOCK */ + /* break; + if (s->frame) + { + memcpy(&t[skip], &s->frame[skip], 4); + skip += s->w; + memcpy(&t[skip], &s->frame[skip], 4); skip += s->w; - memset(&t[skip],typedata,4); + memcpy(&t[skip], &s->frame[skip], 4); skip += s->w; - memset(&t[skip],typedata,4); - break; - case 4: /* V4 DOUBLE BLOCK */ - for (k = 0; k < 2; k ++) - { - smk_huff16_lookup(bs,s->tree[SMK_TREE_FULL],unpack); - for (i = 0; i < 2; i ++) - { - memset(&t[skip + 2],(unpack & 0xFF00) >> 8,2); - memset(&t[skip],(unpack & 0x00FF),2); - skip += s->w; - } + memcpy(&t[skip], &s->frame[skip], 4); + } */ + break; + + case 3: /* SOLID BLOCK */ + memset(&t[skip], typedata, 4); + skip += s->w; + memset(&t[skip], typedata, 4); + skip += s->w; + memset(&t[skip], typedata, 4); + skip += s->w; + memset(&t[skip], typedata, 4); + break; + + case 4: /* V4 DOUBLE BLOCK */ + for (k = 0; k < 2; k ++) { + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n", stderr); + return -1; + } + + for (i = 0; i < 2; i ++) { + memset(&t[skip + 2], (unpack & 0xFF00) >> 8, 2); + memset(&t[skip], (unpack & 0x00FF), 2); + skip += s->w; } - break; - case 5: /* V4 HALF BLOCK */ - for (k = 0; k < 2; k ++) - { - smk_huff16_lookup(bs,s->tree[SMK_TREE_FULL],unpack); - t[skip + 3] = ((unpack & 0xFF00) >> 8); - t[skip + 2] = (unpack & 0x00FF); - t[skip + s->w + 3] = ((unpack & 0xFF00) >> 8); - t[skip + s->w + 2] = (unpack & 0x00FF); - smk_huff16_lookup(bs,s->tree[SMK_TREE_FULL],unpack); - t[skip + 1] = ((unpack & 0xFF00) >> 8); - t[skip] = (unpack & 0x00FF); - t[skip + s->w + 1] = ((unpack & 0xFF00) >> 8); - t[skip + s->w] = (unpack & 0x00FF); - skip += (s->w << 1); + } + + break; + + case 5: /* V4 HALF BLOCK */ + for (k = 0; k < 2; k ++) { + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n", stderr); + return -1; } - break; + + t[skip + 3] = ((unpack & 0xFF00) >> 8); + t[skip + 2] = (unpack & 0x00FF); + t[skip + s->w + 3] = ((unpack & 0xFF00) >> 8); + t[skip + s->w + 2] = (unpack & 0x00FF); + + if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { + fputs("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n", stderr); + return -1; + } + + t[skip + 1] = ((unpack & 0xFF00) >> 8); + t[skip] = (unpack & 0x00FF); + t[skip + s->w + 1] = ((unpack & 0xFF00) >> 8); + t[skip + s->w] = (unpack & 0x00FF); + skip += (s->w << 1); + } + + break; } + col += 4; - if (col >= s->w) - { + + if (col >= s->w) { col = 0; row += 4; } } } - smk_free(bs); - return 0; - -error: - smk_free(bs); - return -1; } /* Decompress audio track i. */ -static char smk_render_audio(struct smk_audio_t* s, unsigned char* p, unsigned long size) +static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned long size) { - unsigned int j,k; - unsigned char* t = s->buffer; - struct smk_bit_t* bs = NULL; - + unsigned int j, k; + unsigned char * t = s->buffer; + struct smk_bit_t bs; char bit; short unpack, unpack2; - /* used for audio decoding */ - struct smk_huff8_t* aud_tree[4] = {NULL,NULL,NULL,NULL}; - - /* sanity check */ - smk_assert(s); - smk_assert(p); + struct smk_huff8_t aud_tree[4]; + /* null check */ + assert(s); + assert(p); - if (!s->compress) - { - /* Raw PCM data, update buffer size and malloc */ + if (!s->compress) { + /* Raw PCM data, update buffer size and perform copy */ s->buffer_size = size; - - memcpy(t,p,size); - } - else if (s->compress == 1) - { + memcpy(t, p, size); + } else if (s->compress == 1) { /* SMACKER DPCM compression */ /* need at least 4 bytes to process */ - if (size < 4) - { - fputs("libsmacker::smk_render_audio() - ERROR: need 4 bytes to get unpacked output buffer size.\n",stderr); + if (size < 4) { + fputs("libsmacker::smk_render_audio() - ERROR: need 4 bytes to get unpacked output buffer size.\n", stderr); goto error; } + /* chunk is compressed (huff-compressed dpcm), retrieve unpacked buffer size */ s->buffer_size = ((unsigned int) p[3] << 24) | - ((unsigned int) p[2] << 16) | - ((unsigned int) p[1] << 8) | - ((unsigned int) p[0]); - + ((unsigned int) p[2] << 16) | + ((unsigned int) p[1] << 8) | + ((unsigned int) p[0]); p += 4; size -= 4; - /* Compressed audio: must unpack here */ /* Set up a bitstream */ - bs = smk_bs_init (p, size); - - smk_bs_read_1(bs,bit); + smk_bs_init(&bs, p, size); + bit = smk_bs_read_1(&bs); - if (!bit) - { - fputs("libsmacker::smk_render_audio - ERROR: initial get_bit returned 0\n",stderr); + if (!bit) { + fputs("libsmacker::smk_render_audio - ERROR: initial get_bit returned 0\n", stderr); goto error; } - smk_bs_read_1(bs,bit); + bit = smk_bs_read_1(&bs); + if (s->channels != (bit == 1 ? 2 : 1)) - { - fputs("libsmacker::smk_render - ERROR: mono/stereo mismatch\n",stderr); - } - smk_bs_read_1(bs,bit); + fputs("libsmacker::smk_render - ERROR: mono/stereo mismatch\n", stderr); + + bit = smk_bs_read_1(&bs); + if (s->bitdepth != (bit == 1 ? 16 : 8)) - { - fputs("libsmacker::smk_render - ERROR: 8-/16-bit mismatch\n",stderr); - } + fputs("libsmacker::smk_render - ERROR: 8-/16-bit mismatch\n", stderr); /* build the trees */ - smk_huff8_build(bs,aud_tree[0]); + smk_huff8_build(&aud_tree[0], &bs); j = 1; k = 1; - if (s->bitdepth == 16) - { - smk_huff8_build(bs,aud_tree[1]); + + if (s->bitdepth == 16) { + smk_huff8_build(&aud_tree[1], &bs); k = 2; } - if (s->channels == 2) - { - smk_huff8_build(bs,aud_tree[2]); + + if (s->channels == 2) { + smk_huff8_build(&aud_tree[2], &bs); j = 2; k = 2; - if (s->bitdepth == 16) - { - smk_huff8_build(bs,aud_tree[3]); + + if (s->bitdepth == 16) { + smk_huff8_build(&aud_tree[3], &bs); k = 4; } } /* read initial sound level */ - if (s->channels == 2) - { - smk_bs_read_8(bs,unpack); - if (s->bitdepth == 16) - { - smk_bs_read_8(bs,((short*)t)[1]) - ((short*)t)[1] |= (unpack << 8); - } - else - { - ((unsigned char*)t)[1] = (unsigned char)unpack; - } - } - smk_bs_read_8(bs,unpack); - if (s->bitdepth == 16) - { - smk_bs_read_8(bs,((short*)t)[0]) - ((short*)t)[0] |= (unpack << 8); - } - else - { - ((unsigned char*)t)[0] = (unsigned char)unpack; + if (s->channels == 2) { + unpack = smk_bs_read_8(&bs); + + if (s->bitdepth == 16) { + ((short *)t)[1] = smk_bs_read_8(&bs); + ((short *)t)[1] |= (unpack << 8); + } else + ((unsigned char *)t)[1] = (unsigned char)unpack; } + unpack = smk_bs_read_8(&bs); + + if (s->bitdepth == 16) { + ((short *)t)[0] = smk_bs_read_8(&bs); + ((short *)t)[0] |= (unpack << 8); + } else + ((unsigned char *)t)[0] = (unsigned char)unpack; + /* All set: let's read some DATA! */ - while (k < s->buffer_size) - { - if (s->bitdepth == 8) - { - smk_huff8_lookup(bs,aud_tree[0],unpack); - ((unsigned char*)t)[j] = (char)unpack + ((unsigned char*)t)[j - s->channels]; + while (k < s->buffer_size) { + if (s->bitdepth == 8) { + unpack = smk_huff8_lookup(&aud_tree[0], &bs); + ((unsigned char *)t)[j] = (char)unpack + ((unsigned char *)t)[j - s->channels]; j ++; k++; - } - else - { - smk_huff8_lookup(bs,aud_tree[0],unpack); - smk_huff8_lookup(bs,aud_tree[1],unpack2); - ((short*)t)[j] = (short) ( unpack | (unpack2 << 8) ) + ((short*)t)[j - s->channels]; + } else { + unpack = smk_huff8_lookup(&aud_tree[0], &bs); + unpack2 = smk_huff8_lookup(&aud_tree[1], &bs); + ((short *)t)[j] = (short)(unpack | (unpack2 << 8)) + ((short *)t)[j - s->channels]; j ++; - k+=2; + k += 2; } - if (s->channels == 2) - { - if (s->bitdepth == 8) - { - smk_huff8_lookup(bs,aud_tree[2],unpack); - ((unsigned char*)t)[j] = (char)unpack + ((unsigned char*)t)[j - 2]; + + if (s->channels == 2) { + if (s->bitdepth == 8) { + unpack = smk_huff8_lookup(&aud_tree[2], &bs); + ((unsigned char *)t)[j] = (char)unpack + ((unsigned char *)t)[j - 2]; j ++; k++; - } - else - { - smk_huff8_lookup(bs,aud_tree[2],unpack); - smk_huff8_lookup(bs,aud_tree[3],unpack2); - ((short*)t)[j] = (short) ( unpack | (unpack2 << 8) ) + ((short*)t)[j - 2]; + } else { + unpack = smk_huff8_lookup(&aud_tree[2], &bs); + unpack2 = smk_huff8_lookup(&aud_tree[3], &bs); + ((short *)t)[j] = (short)(unpack | (unpack2 << 8)) + ((short *)t)[j - 2]; j ++; - k+=2; + k += 2; } } } - - /* All done with the trees, free them. */ - for (j = 0; j < 4; j ++) - { - if (aud_tree[j]) - { - smk_huff8_free(aud_tree[j]); - } - } - - /* free bitstream */ - smk_free(bs); } return 0; - error: - /* All done with the trees, free them. */ - for (j = 0; j < 4; j ++) - { - if (aud_tree[j]) - { - smk_huff8_free(aud_tree[j]); - } - } - - smk_free(bs); - return -1; } @@ -1214,59 +1600,53 @@ error: Preps all the image and audio pointers */ static char smk_render(smk s) { - unsigned long i,size; - unsigned char* buffer = NULL,* p,track; - - /* sanity check */ - smk_assert(s); + unsigned long i, size; + unsigned char * buffer = NULL, * p, track; + /* null check */ + assert(s); /* Retrieve current chunk_size for this frame. */ - if (!(i = s->chunk_size[s->cur_frame])) - { - fprintf(stderr,"libsmacker::smk_render(s) - Warning: frame %lu: chunk_size is 0.\n",s->cur_frame); + if (!(i = s->chunk_size[s->cur_frame])) { + fprintf(stderr, "libsmacker::smk_render(s) - Warning: frame %lu: chunk_size is 0.\n", s->cur_frame); goto error; } - if (s->mode == SMK_MODE_DISK) - { + if (s->mode == SMK_MODE_DISK) { /* Skip to frame in file */ - if (fseek(s->source.file.fp,s->source.file.chunk_offset[s->cur_frame],SEEK_SET)) - { - fprintf(stderr,"libsmacker::smk_render(s) - ERROR: fseek to frame %lu (offset %lu) failed.\n",s->cur_frame,s->source.file.chunk_offset[s->cur_frame]); - perror ("\tError reported was"); + if (fseek(s->source.file.fp, s->source.file.chunk_offset[s->cur_frame], SEEK_SET)) { + fprintf(stderr, "libsmacker::smk_render(s) - ERROR: fseek to frame %lu (offset %lu) failed.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); + perror("\tError reported was"); goto error; } /* In disk-streaming mode: make way for our incoming chunk buffer */ - smk_malloc(buffer, i); + if ((buffer = malloc(i)) == NULL) { + perror("libsmacker::smk_render() - ERROR: failed to malloc() buffer"); + return -1; + } /* Read into buffer */ - if ( smk_read_file(buffer,s->chunk_size[s->cur_frame],s->source.file.fp) < 0) - { - fprintf(stderr,"libsmacker::smk_render(s) - ERROR: frame %lu (offset %lu): smk_read had errors.\n",s->cur_frame,s->source.file.chunk_offset[s->cur_frame]); + if (smk_read_file(buffer, s->chunk_size[s->cur_frame], s->source.file.fp) < 0) { + fprintf(stderr, "libsmacker::smk_render(s) - ERROR: frame %lu (offset %lu): smk_read had errors.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); goto error; } - } - else - { + } else { /* Just point buffer at the right place */ - if (!s->source.chunk_data[s->cur_frame]) - { - fprintf(stderr,"libsmacker::smk_render(s) - ERROR: frame %lu: memory chunk is a NULL pointer.\n",s->cur_frame); + if (!s->source.chunk_data[s->cur_frame]) { + fprintf(stderr, "libsmacker::smk_render(s) - ERROR: frame %lu: memory chunk is a NULL pointer.\n", s->cur_frame); goto error; } + buffer = s->source.chunk_data[s->cur_frame]; } p = buffer; /* Palette record first */ - if (s->frame_type[s->cur_frame] & 0x01) - { + if (s->frame_type[s->cur_frame] & 0x01) { /* need at least 1 byte to process */ - if (!i) - { - fprintf(stderr,"libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for a palette rec.\n",s->cur_frame); + if (!i) { + fprintf(stderr, "libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for a palette rec.\n", s->cur_frame); goto error; } @@ -1276,22 +1656,18 @@ static char smk_render(smk s) /* If video rendering enabled, kick this off for decode. */ if (s->video.enable) - { - smk_render_palette(&(s->video),p + 1,size - 1); - } + smk_render_palette(&(s->video), p + 1, size - 1); + p += size; i -= size; } /* Unpack audio chunks */ - for (track = 0; track < 7; track ++) - { - if (s->frame_type[s->cur_frame] & (0x02 << track)) - { + for (track = 0; track < 7; track ++) { + if (s->frame_type[s->cur_frame] & (0x02 << track)) { /* need at least 4 byte to process */ - if (i < 4) - { - fprintf(stderr,"libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for audio[%u] rec.\n",s->cur_frame,track); + if (i < 4) { + fprintf(stderr, "libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for audio[%u] rec.\n", s->cur_frame, track); goto error; } @@ -1304,35 +1680,31 @@ static char smk_render(smk s) /* If audio rendering enabled, kick this off for decode. */ if (s->audio[track].enable) - { - smk_render_audio(&s->audio[track],p + 4,size - 4); - } + smk_render_audio(&s->audio[track], p + 4, size - 4); + p += size; i -= size; - } - else - { + } else s->audio[track].buffer_size = 0; - } } /* Unpack video chunk */ - if (s->video.enable) - { - smk_render_video(&(s->video), p,i); + if (s->video.enable) { + if (smk_render_video(&(s->video), p, i) < 0) { + fprintf(stderr, "libsmacker::smk_render(s) - ERROR: frame %lu: failed to render video.\n", s->cur_frame); + goto error; + } } - if (s->mode == SMK_MODE_DISK) - { + if (s->mode == SMK_MODE_DISK) { /* Remember that buffer we allocated? Trash it */ smk_free(buffer); } return 0; - error: - if (s->mode == SMK_MODE_DISK) - { + + if (s->mode == SMK_MODE_DISK) { /* Remember that buffer we allocated? Trash it */ smk_free(buffer); } @@ -1343,89 +1715,83 @@ error: /* rewind to first frame and unpack */ char smk_first(smk s) { - smk_assert(s); + /* null check */ + if (s == NULL) { + fputs("libsmacker::smk_first() - ERROR: smk is NULL\n", stderr); + return -1; + } s->cur_frame = 0; - if ( smk_render(s) < 0) - { - fprintf(stderr,"libsmacker::smk_first(s) - Warning: frame %lu: smk_render returned errors.\n",s->cur_frame); - goto error; + + if (smk_render(s) < 0) { + fprintf(stderr, "libsmacker::smk_first(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); + return -1; } if (s->f == 1) return SMK_LAST; - return SMK_MORE; - -error: - return -1; -} -unsigned char smk_palette_updated(smk s) -{ - return s->frame_type[s->cur_frame] & 0x01; + return SMK_MORE; } /* advance to next frame */ char smk_next(smk s) { - smk_assert(s); + /* null check */ + if (s == NULL) { + fputs("libsmacker::smk_next() - ERROR: smk is NULL\n", stderr); + return -1; + } - if (s->cur_frame + 1 < (s->f + s->ring_frame)) - { + if (s->cur_frame + 1 < (s->f + s->ring_frame)) { s->cur_frame ++; - if ( smk_render(s) < 0) - { - fprintf(stderr,"libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n",s->cur_frame); - goto error; + + if (smk_render(s) < 0) { + fprintf(stderr, "libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); + return -1; } + if (s->cur_frame + 1 == (s->f + s->ring_frame)) - { return SMK_LAST; - } + return SMK_MORE; - } - else if (s->ring_frame) - { + } else if (s->ring_frame) { s->cur_frame = 1; - if ( smk_render(s) < 0) - { - fprintf(stderr,"libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n",s->cur_frame); - goto error; + + if (smk_render(s) < 0) { + fprintf(stderr, "libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); + return -1; } + if (s->cur_frame + 1 == (s->f + s->ring_frame)) - { return SMK_LAST; - } + return SMK_MORE; } - return SMK_DONE; -error: - return -1; + return SMK_DONE; } /* seek to a keyframe in an smk */ char smk_seek_keyframe(smk s, unsigned long f) { - smk_assert(s); + /* null check */ + if (s == NULL) { + fputs("libsmacker::smk_seek_keyframe() - ERROR: smk is NULL\n", stderr); + return -1; + } /* rewind (or fast forward!) exactly to f */ s->cur_frame = f; /* roll back to previous keyframe in stream, or 0 if no keyframes exist */ while (s->cur_frame > 0 && !(s->keyframe[s->cur_frame])) - { s->cur_frame --; - } /* render the frame: we're ready */ - if (smk_render(s) < 0) - { - fprintf(stderr,"libsmacker::smk_seek_keyframe(s,%lu) - Warning: frame %lu: smk_render returned errors.\n",f,s->cur_frame); - goto error; + if (smk_render(s) < 0) { + fprintf(stderr, "libsmacker::smk_seek_keyframe(s,%lu) - Warning: frame %lu: smk_render returned errors.\n", f, s->cur_frame); + return -1; } return 0; - -error: - return -1; } diff --git a/3rdParty/libsmacker/smacker.h b/3rdParty/libsmacker/smacker.h index d9deb8523..e79700416 100644 --- a/3rdParty/libsmacker/smacker.h +++ b/3rdParty/libsmacker/smacker.h @@ -26,7 +26,7 @@ #include /** forward-declaration for an struct */ -typedef struct smk_t* smk; +typedef struct smk_t * smk; /** a few defines as return codes from smk_next() */ #define SMK_DONE 0x00 @@ -60,20 +60,20 @@ extern "C" { /* OPEN OPERATIONS */ /** open an smk (from a file) */ -smk smk_open_file(const char* filename, unsigned char mode); +smk smk_open_file(const char * filename, unsigned char mode); /** open an smk (from a file pointer) */ -smk smk_open_filepointer(FILE* file, unsigned char mode); +smk smk_open_filepointer(FILE * file, unsigned char mode); /** read an smk (from a memory buffer) */ -smk smk_open_memory(const unsigned char* buffer, unsigned long size); +smk smk_open_memory(const unsigned char * buffer, unsigned long size); /* CLOSE OPERATIONS */ /** close out an smk file and clean up memory */ void smk_close(smk object); /* GET FILE INFO OPERATIONS */ -char smk_info_all(const smk object, unsigned long* frame, unsigned long* frame_count, double* usf); -char smk_info_video(const smk object, unsigned long* w, unsigned long* h, unsigned char* y_scale_mode); -char smk_info_audio(const smk object, unsigned char* track_mask, unsigned char channels[7], unsigned char bitdepth[7], unsigned long audio_rate[7]); +char smk_info_all(const smk object, unsigned long * frame, unsigned long * frame_count, double * usf); +char smk_info_video(const smk object, unsigned long * w, unsigned long * h, unsigned char * y_scale_mode); +char smk_info_audio(const smk object, unsigned char * track_mask, unsigned char channels[7], unsigned char bitdepth[7], unsigned long audio_rate[7]); /* ENABLE/DISABLE Switches */ char smk_enable_all(smk object, unsigned char mask); @@ -81,18 +81,16 @@ char smk_enable_video(smk object, unsigned char enable); char smk_enable_audio(smk object, unsigned char track, unsigned char enable); /** Retrieve palette */ -const unsigned char* smk_get_palette(const smk object); +const unsigned char * smk_get_palette(const smk object); /** Retrieve video frame, as a buffer of size w*h */ -const unsigned char* smk_get_video(const smk object); +const unsigned char * smk_get_video(const smk object); /** Retrieve decoded audio chunk, track N */ -const unsigned char* smk_get_audio(const smk object, unsigned char track); +const unsigned char * smk_get_audio(const smk object, unsigned char track); /** Get size of currently pointed decoded audio chunk, track N */ unsigned long smk_get_audio_size(const smk object, unsigned char track); /** rewind to first frame and unpack */ char smk_first(smk object); -/** was the pallet updated this frame */ -unsigned char smk_palette_updated(smk s); /** advance to next frame and unpack */ char smk_next(smk object); /** seek to first keyframe before/at N in an smk */ diff --git a/3rdParty/libsmacker/smk_bitstream.c b/3rdParty/libsmacker/smk_bitstream.c deleted file mode 100644 index 35797a747..000000000 --- a/3rdParty/libsmacker/smk_bitstream.c +++ /dev/null @@ -1,119 +0,0 @@ -/** - libsmacker - A C library for decoding .smk Smacker Video files - Copyright (C) 2012-2017 Greg Kennedy - - See smacker.h for more information. - - smk_bitstream.c - Implements a bitstream structure, which can extract and - return a bit at a time from a raw block of bytes. -*/ - -#include "smk_bitstream.h" - -/* malloc and friends */ -#include "smk_malloc.h" - -/* - Bitstream structure - Pointer to raw block of data and a size limit. - Maintains internal pointers to byte_num and bit_number. -*/ -struct smk_bit_t -{ - const unsigned char* buffer; - unsigned long size; - - unsigned long byte_num; - char bit_num; -}; - -/* BITSTREAM Functions */ -struct smk_bit_t* smk_bs_init(const unsigned char* b, const unsigned long size) -{ - struct smk_bit_t* ret = NULL; - - /* sanity check */ - smk_assert(b); - - /* allocate a bitstream struct */ - smk_malloc(ret, sizeof(struct smk_bit_t)); - - /* set up the pointer to bitstream, and the size counter */ - ret->buffer = b; - ret->size = size; - - /* point to initial byte: note, smk_malloc already sets these to 0 */ - /* ret->byte_num = 0; - ret->bit_num = 0; */ - - /* return ret or NULL if error : ) */ -error: - return ret; -} - -/* Reads a bit - Returns -1 if error encountered */ -char _smk_bs_read_1(struct smk_bit_t* bs) -{ - unsigned char ret = -1; - - /* sanity check */ - smk_assert(bs); - - /* don't die when running out of bits, but signal */ - if (bs->byte_num >= bs->size) - { - fprintf(stderr, "libsmacker::_smk_bs_read_1(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs->size); - goto error; - } - - /* get next bit and return */ - ret = (((bs->buffer[bs->byte_num]) & (1 << bs->bit_num)) != 0); - - /* advance to next bit */ - bs->bit_num ++; - - /* Out of bits in this byte: next! */ - if (bs->bit_num > 7) - { - bs->byte_num ++; - bs->bit_num = 0; - } - - /* return ret, or (default) -1 if error */ -error: - return ret; -} - -/* Reads a byte - Returns -1 if error. */ -short _smk_bs_read_8(struct smk_bit_t* bs) -{ - unsigned char ret = -1; - - /* sanity check */ - smk_assert(bs); - - /* don't die when running out of bits, but signal */ - if (bs->byte_num + (bs->bit_num > 0) >= bs->size) - { - fprintf(stderr, "libsmacker::_smk_bs_read_8(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs->size); - goto error; - } - - if (bs->bit_num) - { - /* unaligned read */ - ret = bs->buffer[bs->byte_num] >> bs->bit_num; - bs->byte_num ++; - ret |= (bs->buffer[bs->byte_num] << (8 - bs->bit_num)); - } else { - /* aligned read */ - ret = bs->buffer[bs->byte_num ++]; - } - - /* return ret, or (default) -1 if error */ -error: - return ret; -} diff --git a/3rdParty/libsmacker/smk_bitstream.h b/3rdParty/libsmacker/smk_bitstream.h deleted file mode 100644 index 3a99e209e..000000000 --- a/3rdParty/libsmacker/smk_bitstream.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - libsmacker - A C library for decoding .smk Smacker Video files - Copyright (C) 2012-2017 Greg Kennedy - - See smacker.h for more information. - - smk_bitstream.h - SMK bitstream structure. Presents a block of raw bytes one - bit at a time, and protects against over-read. -*/ - -#ifndef SMK_BITSTREAM_H -#define SMK_BITSTREAM_H - -/** Bitstream structure, Forward declaration */ -struct smk_bit_t; - -/* BITSTREAM Functions */ -/** Initialize a bitstream */ -struct smk_bit_t* smk_bs_init(const unsigned char* b, unsigned long size); - -/** This macro checks return code from _smk_bs_read_1 and - jumps to error label if problems occur. */ -#define smk_bs_read_1(t,uc) \ -{ \ - if ((char)(uc = _smk_bs_read_1(t)) < 0) \ - { \ - fprintf(stderr, "libsmacker::smk_bs_read_1(" #t ", " #uc ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/** Read a single bit from the bitstream, and advance. - Returns -1 on error. */ -char _smk_bs_read_1(struct smk_bit_t* bs); - -/** This macro checks return code from _smk_bs_read_8 and - jumps to error label if problems occur. */ -#define smk_bs_read_8(t,s) \ -{ \ - if ((short)(s = _smk_bs_read_8(t)) < 0) \ - { \ - fprintf(stderr, "libsmacker::smk_bs_read_8(" #t ", " #s ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/** Read eight bits from the bitstream (one byte), and advance. - Returns -1 on error. */ -short _smk_bs_read_8(struct smk_bit_t* bs); - -#endif diff --git a/3rdParty/libsmacker/smk_hufftree.c b/3rdParty/libsmacker/smk_hufftree.c deleted file mode 100644 index cd6c98d0d..000000000 --- a/3rdParty/libsmacker/smk_hufftree.c +++ /dev/null @@ -1,425 +0,0 @@ -/** - libsmacker - A C library for decoding .smk Smacker Video files - Copyright (C) 2012-2017 Greg Kennedy - - See smacker.h for more information. - - smk_hufftree.c - Implementation of Smacker Huffman coding trees. -*/ - -#include "smk_hufftree.h" - -/* malloc and friends */ -#include "smk_malloc.h" - -/** - 8-bit Tree node structure. - If b0 is non-null, this is a branch, and b1 from the union should be used. - If b0 is null, this is a leaf, and val / escape code from union should be used. -*/ -struct smk_huff8_t -{ - struct smk_huff8_t* b0; - union - { - struct smk_huff8_t* b1; - struct - { - unsigned short value; - unsigned char escapecode; - } leaf; - } u; -}; - -/** - 16-bit Tree root struct: holds a huff8_t structure, - as well as a cache of three 16-bit values. -*/ -struct smk_huff16_t -{ - struct smk_huff8_t* t; - unsigned short cache[3]; -}; - -/*********************** 8-BIT HUFF-TREE FUNCTIONS ***********************/ -/** safe build with built-in error jump */ -#define smk_huff8_build_rec(bs,p) \ -{ \ - if (!(p = _smk_huff8_build_rec(bs))) \ - { \ - fprintf(stderr, "libsmacker::smk_huff8_build_rec(" #bs ", " #p ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/** Recursive tree-building function. */ -static struct smk_huff8_t* _smk_huff8_build_rec(struct smk_bit_t* bs) -{ - struct smk_huff8_t* ret = NULL; - char bit; - - /* sanity check - removed: bs cannot be null, because it was checked at smk_huff8_build below */ - /* smk_assert(bs); */ - - /* Read the bit */ - smk_bs_read_1(bs, bit); - - /* Malloc a structure. */ - smk_malloc(ret, sizeof(struct smk_huff8_t)); - - if (bit) - { - /* Bit set: this forms a Branch node. */ - /* Recursively attempt to build the Left branch. */ - smk_huff8_build_rec(bs, ret->b0); - - /* Everything is still OK: attempt to build the Right branch. */ - smk_huff8_build_rec(bs, ret->u.b1); - - /* return branch pointer here */ - return ret; - } - - /* Bit unset signifies a Leaf node. */ - /* Attempt to read value */ - smk_bs_read_8(bs, ret->u.leaf.value); - - /* smk_malloc sets entries to 0 by default */ - /* ret->b0 = NULL; */ - ret->u.leaf.escapecode = 0xFF; - - return ret; - -error: - /* In case of error, undo the subtree we were building, and return NULL. */ - smk_huff8_free(ret); - return NULL; -} - -/* Look up an 8-bit value from a basic huff tree. - Return -1 on error. */ -short _smk_huff8_lookup(struct smk_bit_t* bs, const struct smk_huff8_t* t) -{ - char bit; - - /* sanity check */ - smk_assert(bs); - smk_assert(t); - - if (!t->b0) - { - /* Reached a Leaf node. Return its value. */ - return t->u.leaf.value; - } - - /* Read the next bit from bitstream to determine path */ - smk_bs_read_1(bs, bit); - - if (bit) - { - /* get_bit returned Set, follow Right branch. */ - return _smk_huff8_lookup(bs, t->u.b1); - } - - /* follow Left branch */ - return _smk_huff8_lookup(bs, t->b0); - -error: - return -1; -} - -/** - Entry point for huff8 build. Basically just checks the start/end tags - and calls smk_huff8_build_rec recursive function. -*/ -struct smk_huff8_t* _smk_huff8_build(struct smk_bit_t* bs) -{ - struct smk_huff8_t* ret = NULL; - char bit; - - /* sanity check */ - smk_assert(bs); - - /* Smacker huff trees begin with a set-bit. */ - smk_bs_read_1(bs, bit); - - if (!bit) - { - /* Got a bit, but it was not 1. In theory, there could be a smk file - without this particular tree. */ - fputs("libsmacker::_smk_huff8_build(bs) - Warning: initial get_bit returned 0\n", stderr); - goto error; - } - - /* Begin parsing the tree data. */ - smk_huff8_build_rec(bs, ret); - - /* huff trees end with an unset-bit */ - smk_bs_read_1(bs, bit); - - if (bit) - { - fputs("libsmacker::_smk_huff8_build(bs) - ERROR: final get_bit returned 1\n", stderr); - goto error; - } - - return ret; - -error: - smk_huff8_free(ret); - return NULL; -} - -/* function to recursively delete a huffman tree */ -void smk_huff8_free(struct smk_huff8_t* t) -{ - /* Sanity check: do not double-free */ - smk_assert(t); - - /* If this is not a leaf node, free child trees first */ - if (t->b0) - { - smk_huff8_free(t->b0); - smk_huff8_free(t->u.b1); - } - - /* Safe-delete tree node. */ - smk_free(t); - -error: ; -} - -/*********************** 16-BIT HUFF-TREE FUNCTIONS ***********************/ -/* safe bigtree build with built-in error jump */ -#define smk_huff16_build_rec(bs,cache,low8,hi8,p) \ -{ \ - if (!(p = _smk_huff16_build_rec(bs, cache, low8, hi8))) \ - { \ - fprintf(stderr, "libsmacker::smk_huff16_build_rec(" #bs ", " #cache ", " #low8 ", " #hi8 ", " #p ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/* Recursively builds a Big tree. */ -static struct smk_huff8_t* _smk_huff16_build_rec(struct smk_bit_t* bs, const unsigned short cache[3], const struct smk_huff8_t* low8, const struct smk_huff8_t* hi8) -{ - struct smk_huff8_t* ret = NULL; - - char bit; - short lowval; - - /* sanity check - removed: these cannot be null, because they were checked at smk_huff16_build below */ - /* smk_assert(bs); - smk_assert(cache); - smk_assert(low8); - smk_assert(hi8); */ - - /* Get the first bit */ - smk_bs_read_1(bs, bit); - - /* Malloc a structure. */ - smk_malloc(ret, sizeof(struct smk_huff8_t)); - - if (bit) - { - /* Recursively attempt to build the Left branch. */ - smk_huff16_build_rec(bs, cache, low8, hi8, ret->b0); - - /* Recursively attempt to build the Left branch. */ - smk_huff16_build_rec(bs, cache, low8, hi8, ret->u.b1); - - /* return branch pointer here */ - return ret; - } - - /* Bit unset signifies a Leaf node. */ - smk_huff8_lookup(bs, low8, lowval); - smk_huff8_lookup(bs, hi8, ret->u.leaf.value); - - /* Looks OK: we got low and hi values. Return a new LEAF */ - /* ret->b0 = NULL; */ - ret->u.leaf.value = lowval | (ret->u.leaf.value << 8); - - /* Last: when building the tree, some Values may correspond to cache positions. - Identify these values and set the Escape code byte accordingly. */ - if (ret->u.leaf.value == cache[0]) - { - ret->u.leaf.escapecode = 0; - } - else if (ret->u.leaf.value == cache[1]) - { - ret->u.leaf.escapecode = 1; - } - else if (ret->u.leaf.value == cache[2]) - { - ret->u.leaf.escapecode = 2; - } - else - { - ret->u.leaf.escapecode = 0xFF; - } - - return ret; - -error: - smk_huff8_free(ret); - return NULL; -} - -/* Entry point for building a big 16-bit tree. */ -struct smk_huff16_t* _smk_huff16_build(struct smk_bit_t* bs) -{ - struct smk_huff16_t* big = NULL; - - struct smk_huff8_t* low8 = NULL; - struct smk_huff8_t* hi8 = NULL; - - short lowval; - - char bit; - unsigned char i; - - /* sanity check */ - smk_assert(bs); - - /* Smacker huff trees begin with a set-bit. */ - smk_bs_read_1(bs, bit); - - if (!bit) - { - fputs("libsmacker::smk_huff16_build(bs) - ERROR: initial get_bit returned 0\n", stderr); - goto error; - } - - /* build low-8-bits tree */ - smk_huff8_build(bs, low8); - /* build hi-8-bits tree */ - smk_huff8_build(bs, hi8); - - /* Everything looks OK so far. Time to malloc structure. */ - smk_malloc(big, sizeof(struct smk_huff16_t)); - - /* Init the escape code cache. */ - for (i = 0; i < 3; i ++) - { - smk_bs_read_8(bs, lowval); - smk_bs_read_8(bs, big->cache[i]); - big->cache[i] = lowval | (big->cache[i] << 8); - } - - /* Finally, call recursive function to retrieve the Bigtree. */ - smk_huff16_build_rec(bs, big->cache, low8, hi8, big->t); - - /* Done with 8-bit hufftrees, free them. */ - smk_huff8_free(hi8); - smk_huff8_free(low8); - - /* Check final end tag. */ - smk_bs_read_1(bs, bit); - - if (bit) - { - fputs("libsmacker::smk_huff16_build(bs) - ERROR: final get_bit returned 1\n", stderr); - goto error; - } - - return big; - -error: - smk_huff16_free(big); - smk_huff8_free(hi8); - smk_huff8_free(low8); - return NULL; -} - -static int _smk_huff16_lookup_rec(struct smk_bit_t* bs, unsigned short cache[3], const struct smk_huff8_t* t) -{ - unsigned short val; - char bit; - - /* sanity check */ - /* smk_assert(bs); - smk_assert(cache); - smk_assert(t); */ - - /* Reached a Leaf node */ - if (!t->b0) - { - if (t->u.leaf.escapecode != 0xFF) - { - /* Found escape code. Retrieve value from Cache. */ - val = cache[t->u.leaf.escapecode]; - } - else - { - /* Use value directly. */ - val = t->u.leaf.value; - } - - if (cache[0] != val) - { - /* Update the cache, by moving val to the front of the queue, - if it isn't already there. */ - cache[2] = cache[1]; - cache[1] = cache[0]; - cache[0] = val; - } - - return val; - } - - /* Read the next bit from bitstream to determine path */ - smk_bs_read_1(bs, bit); - - if (bit) - { - /* get_bit returned Set, follow Right branch. */ - return _smk_huff16_lookup_rec(bs, cache, t->u.b1); - } - - return _smk_huff16_lookup_rec(bs, cache, t->b0); - -error: - return -1; -} - -/* Convenience call-out for recursive bigtree lookup function */ -long _smk_huff16_lookup(struct smk_bit_t* bs, struct smk_huff16_t* big) -{ - /* sanity check */ - smk_assert(bs); - smk_assert(big); - - return _smk_huff16_lookup_rec(bs, big->cache, big->t); - -error: - return -1; -} - -/* Resets a Big hufftree cache */ -void smk_huff16_reset(struct smk_huff16_t* big) -{ - /* sanity check */ - smk_assert(big); - - big->cache[0] = 0; - big->cache[1] = 0; - big->cache[2] = 0; - -error: ; -} - -/* delete a (big) huffman tree */ -void smk_huff16_free(struct smk_huff16_t* big) -{ - /* Sanity check: do not double-free */ - smk_assert(big); - - /* free the subtree */ - if (big->t) - smk_huff8_free(big->t); - - /* free the bigtree */ - smk_free(big); - -error: ; -}; diff --git a/3rdParty/libsmacker/smk_hufftree.h b/3rdParty/libsmacker/smk_hufftree.h deleted file mode 100644 index ff200f88d..000000000 --- a/3rdParty/libsmacker/smk_hufftree.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - libsmacker - A C library for decoding .smk Smacker Video files - Copyright (C) 2012-2017 Greg Kennedy - - See smacker.h for more information. - - smk_hufftree.h - SMK huffmann trees. There are two types: - - a basic 8-bit tree, and - - a "big" 16-bit tree which includes a cache for recently - searched values. -*/ - -#ifndef SMK_HUFFTREE_H -#define SMK_HUFFTREE_H - -#include "smk_bitstream.h" - -/** Tree node structures - Forward declaration */ -struct smk_huff8_t; -struct smk_huff16_t; - -/*********************** 8-BIT HUFF-TREE FUNCTIONS ***********************/ -/** This macro checks return code from _smk_huff8_build and - jumps to error label if problems occur. */ -#define smk_huff8_build(bs,t) \ -{ \ - if (!(t = _smk_huff8_build(bs))) \ - { \ - fprintf(stderr, "libsmacker::smk_huff8_build(" #bs ", " #t ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/** Build an 8-bit tree from a bitstream */ -struct smk_huff8_t* _smk_huff8_build(struct smk_bit_t* bs); - -/** This macro checks return code from _smk_huff8_lookup and - jumps to error label if problems occur. */ -#define smk_huff8_lookup(bs,t,s) \ -{ \ - if ((short)(s = _smk_huff8_lookup(bs, t)) < 0) \ - { \ - fprintf(stderr, "libsmacker::smk_huff8_lookup(" #bs ", " #t ", " #s ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/** Look up an 8-bit value in the referenced tree by following a bitstream - returns -1 on error */ -short _smk_huff8_lookup(struct smk_bit_t* bs, const struct smk_huff8_t* t); - -/** function to recursively delete an 8-bit huffman tree */ -void smk_huff8_free(struct smk_huff8_t* t); - -/************************ 16-BIT HUFF-TREE FUNCTIONS ************************/ -/** This macro checks return code from _smk_huff16_build and - jumps to error label if problems occur. */ -#define smk_huff16_build(bs,t) \ -{ \ - if (!(t = _smk_huff16_build(bs))) \ - { \ - fprintf(stderr, "libsmacker::smk_huff16_build(" #bs ", " #t ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/** Build a 16-bit tree from a bitstream */ -struct smk_huff16_t* _smk_huff16_build(struct smk_bit_t* bs); - -/** This macro checks return code from smk_huff16_lookup and - jumps to error label if problems occur. */ -#define smk_huff16_lookup(bs,t,s) \ -{ \ - if ((s = _smk_huff16_lookup(bs, t)) < 0) \ - { \ - fprintf(stderr, "libsmacker::smk_huff16_lookup(" #bs ", " #t ", " #s ") - ERROR (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - goto error; \ - } \ -} -/** Look up a 16-bit value in the bigtree by following a bitstream - returns -1 on error */ -long _smk_huff16_lookup(struct smk_bit_t* bs, struct smk_huff16_t* big); - -/** Reset the cache in a 16-bit tree */ -void smk_huff16_reset(struct smk_huff16_t* big); - -/** function to recursively delete a 16-bit huffman tree */ -void smk_huff16_free(struct smk_huff16_t* big); - -#endif diff --git a/3rdParty/libsmacker/smk_malloc.h b/3rdParty/libsmacker/smk_malloc.h index ef70cb79a..cf944e7f9 100644 --- a/3rdParty/libsmacker/smk_malloc.h +++ b/3rdParty/libsmacker/smk_malloc.h @@ -12,6 +12,8 @@ #ifndef SMK_MALLOC_H #define SMK_MALLOC_H +/* assert */ +#include /* calloc */ #include /* fprintf */ @@ -21,34 +23,15 @@ #include #include -/** - Verbose assert: - branches to an error block if pointer is null -*/ -#define smk_assert(p) \ -{ \ - if (!p) \ - { \ - fprintf(stderr, "libsmacker::smk_assert(" #p "): ERROR: NULL POINTER at line %lu, file %s\n", (unsigned long)__LINE__, __FILE__); \ - goto error; \ - } \ -} - /** Safe free: attempts to prevent double-free by setting pointer to NULL. Optionally warns on attempts to free a NULL pointer. */ #define smk_free(p) \ { \ - if (p) \ - { \ - free(p); \ - p = NULL; \ - } \ -/* else \ - { \ - fprintf(stderr, "libsmacker::smk_free(" #p ") - Warning: attempt to free NULL pointer (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ - } */ \ + assert (p); \ + free(p); \ + p = NULL; \ } /** @@ -60,11 +43,7 @@ */ #define smk_malloc(p, x) \ { \ -/* if (p) \ - { \ - fprintf(stderr, "libsmacker::smk_malloc(" #p ", %lu) - Warning: freeing non-NULL pointer before calloc (file: %s, line: %lu)\n", (unsigned long) (x), __FILE__, (unsigned long)__LINE__); \ - free(p); \ - } */ \ + assert (p == NULL); \ p = calloc(1, x); \ if (!p) \ { \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dc625e51..dc37ce492 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,8 +285,6 @@ if(NOT NOSOUND) endif() add_library(smacker STATIC - 3rdParty/libsmacker/smk_bitstream.c - 3rdParty/libsmacker/smk_hufftree.c 3rdParty/libsmacker/smacker.c) target_include_directories(smacker PUBLIC 3rdParty/libsmacker)