diff options
Diffstat (limited to 'src/lib/util/avcomp.c')
-rw-r--r-- | src/lib/util/avcomp.c | 898 |
1 files changed, 0 insertions, 898 deletions
diff --git a/src/lib/util/avcomp.c b/src/lib/util/avcomp.c deleted file mode 100644 index 91fa483d16c..00000000000 --- a/src/lib/util/avcomp.c +++ /dev/null @@ -1,898 +0,0 @@ -/*************************************************************************** - - avcomp.c - - Audio/video compression and decompression helpers. - -**************************************************************************** - - Copyright Aaron Giles - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name 'MAME' nor the names of its contributors may be - used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -**************************************************************************** - - Each frame is compressed as a unit. The raw data is of the form: - (all multibyte values are stored in big-endian format) - - +00 = 'chav' (4 bytes) - fixed header data to identify the format - +04 = metasize (1 byte) - size of metadata in bytes (max=255 bytes) - +05 = channels (1 byte) - number of audio channels - +06 = samples (2 bytes) - number of samples per audio stream - +08 = width (2 bytes) - width of video data - +0A = height (2 bytes) - height of video data - +0C = <metadata> - as raw bytes - <audio stream 0> - as signed 16-bit samples - <audio stream 1> - as signed 16-bit samples - ... - <video data> - as a raw array of 8-bit YUY data in (Cb,Y,Cr,Y) order - - When compressed, the data is stored as follows: - (all multibyte values are stored in big-endian format) - - +00 = metasize (1 byte) - size of metadata in bytes - +01 = channels (1 byte) - number of audio channels - +02 = samples (2 bytes) - number of samples per audio stream - +04 = width (2 bytes) - width of video data - +06 = height (2 bytes) - height of video data - +08 = audio huffman size (2 bytes) - size of audio huffman tables - +0A = str0size (2 bytes) - compressed size of stream 0 - +0C = str1size (2 bytes) - compressed size of stream 1 - ... - <metadata> - as raw data - <audio huffman table> - Huffman table for audio decoding - <audio stream 0 data> - Huffman-compressed deltas - <audio stream 1 data> - Huffman-compressed deltas - <...> - <video huffman tables> - Huffman tables for video decoding - <video data> - compressed data - -**************************************************************************** - - Attempted techniques that have not been worthwhile: - - * Attempted to use integer DCTs from the IJG code; even the "slow" - variants produce a lot of error and thus kill our compression ratio, - since our compression is based on error not bitrate. - - * Tried various other predictors for the lossless video encoding, but - none tended to give any significant gain over predicting the - previous pixel. - -***************************************************************************/ - -#include "avcomp.h" -#include "huffman.h" -#include "chd.h" - -#include <math.h> -#include <stdlib.h> -#include <new> - - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -#define MAX_CHANNELS 4 - - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -struct avcomp_state -{ - avcomp_state() - : maxwidth(0), - maxheight(0), - maxchannels(0), - audiodata(NULL), - ycontext(NULL), - cbcontext(NULL), - crcontext(NULL), - audiohicontext(NULL), - audiolocontext(NULL) { } - - /* video parameters */ - UINT32 maxwidth, maxheight; - - /* audio parameters */ - UINT32 maxchannels; - - /* intermediate data */ - UINT8 * audiodata; - - /* huffman contexts */ - huffman_context * ycontext; - huffman_context * cbcontext; - huffman_context * crcontext; - huffman_context * audiohicontext; - huffman_context * audiolocontext; - - /* configuration data */ - av_codec_compress_config compress; - av_codec_decompress_config decompress; -}; - - - -/*************************************************************************** - PROTOTYPES -***************************************************************************/ - -/* encoding helpers */ -static avcomp_error encode_audio(avcomp_state *state, int channels, int samples, const UINT8 **source, int sourcexor, UINT8 *dest, UINT8 *sizes); -static avcomp_error encode_video(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 sstride, UINT32 sxor, UINT8 *dest, UINT32 *complength); -static avcomp_error encode_video_lossless(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 sstride, UINT32 sxor, UINT8 *dest, UINT32 *complength); - -/* decoding helpers */ -static avcomp_error decode_audio(avcomp_state *state, int channels, int samples, const UINT8 *source, UINT8 **dest, UINT32 dxor, const UINT8 *sizes); -static avcomp_error decode_video(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 complength, UINT8 *dest, UINT32 dstride, UINT32 dxor); -static avcomp_error decode_video_lossless(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 complength, UINT8 *dest, UINT32 deststride, UINT32 destxor); - - - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -/*------------------------------------------------- - avcomp_init - allocate and initialize a - new state block for compression or - decompression --------------------------------------------------*/ - -avcomp_state *avcomp_init(UINT32 maxwidth, UINT32 maxheight, UINT32 maxchannels) -{ - huffman_error hufferr; - avcomp_state *state; - - /* error if out of range */ - if (maxchannels > MAX_CHANNELS) - return NULL; - - /* allocate memory for state block */ - state = new(std::nothrow) avcomp_state; - if (state == NULL) - return NULL; - - /* compute the core info */ - state->maxwidth = maxwidth; - state->maxheight = maxheight; - state->maxchannels = maxchannels; - - /* now allocate data buffers */ - state->audiodata = new(std::nothrow) UINT8[65536 * state->maxchannels * 2]; - if (state->audiodata == NULL) - goto cleanup; - - /* create huffman contexts */ - hufferr = huffman_create_context(&state->ycontext, 16); - if (hufferr != HUFFERR_NONE) - goto cleanup; - hufferr = huffman_create_context(&state->cbcontext, 16); - if (hufferr != HUFFERR_NONE) - goto cleanup; - hufferr = huffman_create_context(&state->crcontext, 16); - if (hufferr != HUFFERR_NONE) - goto cleanup; - hufferr = huffman_create_context(&state->audiohicontext, 16); - if (hufferr != HUFFERR_NONE) - goto cleanup; - hufferr = huffman_create_context(&state->audiolocontext, 16); - if (hufferr != HUFFERR_NONE) - goto cleanup; - - return state; - -cleanup: - avcomp_free(state); - return NULL; -} - - -/*------------------------------------------------- - avcomp_free - free a state block --------------------------------------------------*/ - -void avcomp_free(avcomp_state *state) -{ - /* free the data buffers */ - delete[] state->audiodata; - - /* free the contexts */ - if (state->ycontext != NULL) - huffman_free_context(state->ycontext); - if (state->cbcontext != NULL) - huffman_free_context(state->cbcontext); - if (state->crcontext != NULL) - huffman_free_context(state->crcontext); - if (state->audiohicontext != NULL) - huffman_free_context(state->audiohicontext); - if (state->audiolocontext != NULL) - huffman_free_context(state->audiolocontext); - - delete state; -} - - -/*------------------------------------------------- - avcomp_config_compress - configure compression - parameters --------------------------------------------------*/ - -void avcomp_config_compress(avcomp_state *state, av_codec_compress_config *config) -{ - state->compress.video.wrap(config->video, config->video.cliprect()); - state->compress.channels = config->channels; - state->compress.samples = config->samples; - memcpy(state->compress.audio, config->audio, sizeof(state->compress.audio)); - state->compress.metalength = config->metalength; - state->compress.metadata = config->metadata; -} - - -/*------------------------------------------------- - avcomp_config_decompress - configure - decompression parameters --------------------------------------------------*/ - -void avcomp_config_decompress(avcomp_state *state, av_codec_decompress_config *config) -{ - state->decompress.video.wrap(config->video, config->video.cliprect()); - state->decompress.maxsamples = config->maxsamples; - state->decompress.actsamples = config->actsamples; - memcpy(state->decompress.audio, config->audio, sizeof(state->decompress.audio)); - state->decompress.maxmetalength = config->maxmetalength; - state->decompress.actmetalength = config->actmetalength; - state->decompress.metadata = config->metadata; -} - - - -/*************************************************************************** - ENCODING/DECODING FRONTENDS -***************************************************************************/ - -/*------------------------------------------------- - avcomp_encode_data - encode a block of data - into a compressed data stream --------------------------------------------------*/ - -avcomp_error avcomp_encode_data(avcomp_state *state, const UINT8 *source, UINT8 *dest, UINT32 *complength) -{ - const UINT8 *metastart, *videostart, *audiostart[MAX_CHANNELS]; - UINT32 metasize, channels, samples, width, height; - UINT32 audioxor, videoxor, videostride; - avcomp_error err; - UINT32 dstoffs; - int chnum; - - /* extract data from source if present */ - if (source != NULL) - { - /* validate the header */ - if (source[0] != 'c' || source[1] != 'h' || source[2] != 'a' || source[3] != 'v') - return AVCERR_INVALID_DATA; - - /* extract info from the header */ - metasize = source[4]; - channels = source[5]; - samples = (source[6] << 8) + source[7]; - width = (source[8] << 8) + source[9]; - height = (source[10] << 8) + source[11]; - - /* determine the start of each piece of data */ - source += 12; - metastart = source; - source += metasize; - for (chnum = 0; chnum < channels; chnum++) - { - audiostart[chnum] = source; - source += 2 * samples; - } - videostart = source; - - /* data is assumed to be big-endian already */ - audioxor = videoxor = 0; - videostride = 2 * width; - } - - /* otherwise, extract from the state */ - else - { - UINT16 betest = 0; - - /* extract metadata information */ - metastart = state->compress.metadata; - metasize = state->compress.metalength; - if ((metastart == NULL && metasize != 0) || (metastart != NULL && metasize == 0)) - return AVCERR_INVALID_CONFIGURATION; - - /* extract audio information */ - channels = state->compress.channels; - samples = state->compress.samples; - for (chnum = 0; chnum < channels; chnum++) - audiostart[chnum] = (const UINT8 *)state->compress.audio[chnum]; - - /* extract video information */ - videostart = NULL; - videostride = width = height = 0; - if (state->compress.video.valid()) - { - videostart = reinterpret_cast<const UINT8 *>(&state->compress.video.pix(0)); - videostride = state->compress.video.rowpixels() * 2; - width = state->compress.video.width(); - height = state->compress.video.height(); - } - - /* data is assumed to be native-endian */ - *(UINT8 *)&betest = 1; - audioxor = videoxor = (betest == 1) ? 1 : 0; - } - - /* validate the info from the header */ - if (width > state->maxwidth || height > state->maxheight) - return AVCERR_VIDEO_TOO_LARGE; - if (channels > state->maxchannels) - return AVCERR_AUDIO_TOO_LARGE; - - /* write the basics to the new header */ - dest[0] = metasize; - dest[1] = channels; - dest[2] = samples >> 8; - dest[3] = samples; - dest[4] = width >> 8; - dest[5] = width; - dest[6] = height >> 8; - dest[7] = height; - - /* starting offsets */ - dstoffs = 10 + 2 * channels; - - /* copy the metadata first */ - if (metasize > 0) - { - memcpy(dest + dstoffs, metastart, metasize); - dstoffs += metasize; - } - - /* encode the audio channels */ - if (channels > 0) - { - /* encode the audio */ - err = encode_audio(state, channels, samples, audiostart, audioxor, dest + dstoffs, &dest[8]); - if (err != AVCERR_NONE) - return err; - - /* advance the pointers past the data */ - dstoffs += (dest[8] << 8) + dest[9]; - for (chnum = 0; chnum < channels; chnum++) - dstoffs += (dest[10 + 2 * chnum] << 8) + dest[11 + 2 * chnum]; - } - - /* encode the video data */ - if (width > 0 && height > 0) - { - UINT32 vidlength = 0; - - /* encode the video */ - err = encode_video(state, width, height, videostart, videostride, videoxor, dest + dstoffs, &vidlength); - if (err != AVCERR_NONE) - return err; - - /* advance the pointers past the data */ - dstoffs += vidlength; - } - - /* set the total compression */ - *complength = dstoffs; - return AVCERR_NONE; -} - - -/*------------------------------------------------- - avcomp_decode_data - decode both - audio and video from a raw data stream --------------------------------------------------*/ - -avcomp_error avcomp_decode_data(avcomp_state *state, const UINT8 *source, UINT32 complength, UINT8 *dest) -{ - UINT8 *metastart, *videostart, *audiostart[MAX_CHANNELS]; - UINT32 metasize, channels, samples, width, height; - UINT32 audioxor, videoxor, videostride; - UINT32 srcoffs, totalsize; - avcomp_error err; - int chnum; - - /* extract info from the header */ - if (complength < 8) - return AVCERR_INVALID_DATA; - metasize = source[0]; - channels = source[1]; - samples = (source[2] << 8) + source[3]; - width = (source[4] << 8) + source[5]; - height = (source[6] << 8) + source[7]; - - /* validate the info from the header */ - if (width > state->maxwidth || height > state->maxheight) - return AVCERR_VIDEO_TOO_LARGE; - if (channels > state->maxchannels) - return AVCERR_AUDIO_TOO_LARGE; - - /* validate that the sizes make sense */ - if (complength < 10 + 2 * channels) - return AVCERR_INVALID_DATA; - totalsize = 10 + 2 * channels; - totalsize += (source[8] << 8) | source[9]; - for (chnum = 0; chnum < channels; chnum++) - totalsize += (source[10 + 2 * chnum] << 8) | source[11 + 2 * chnum]; - if (totalsize >= complength) - return AVCERR_INVALID_DATA; - - /* starting offsets */ - srcoffs = 10 + 2 * channels; - - /* if we are decoding raw, set up the output parameters */ - if (dest != NULL) - { - /* create a header */ - dest[0] = 'c'; - dest[1] = 'h'; - dest[2] = 'a'; - dest[3] = 'v'; - dest[4] = metasize; - dest[5] = channels; - dest[6] = samples >> 8; - dest[7] = samples; - dest[8] = width >> 8; - dest[9] = width; - dest[10] = height >> 8; - dest[11] = height; - - /* determine the start of each piece of data */ - dest += 12; - metastart = dest; - dest += metasize; - for (chnum = 0; chnum < channels; chnum++) - { - audiostart[chnum] = dest; - dest += 2 * samples; - } - videostart = dest; - - /* data is assumed to be big-endian already */ - audioxor = videoxor = 0; - videostride = 2 * width; - } - - /* otherwise, extract from the state */ - else - { - UINT16 betest = 0; - - /* determine the start of each piece of data */ - metastart = state->decompress.metadata; - for (chnum = 0; chnum < channels; chnum++) - audiostart[chnum] = (UINT8 *)state->decompress.audio[chnum]; - videostart = (state->decompress.video.valid()) ? reinterpret_cast<UINT8 *>(&state->decompress.video.pix(0)) : NULL; - videostride = (state->decompress.video.valid()) ? state->decompress.video.rowpixels() * 2 : 0; - - /* data is assumed to be native-endian */ - *(UINT8 *)&betest = 1; - audioxor = videoxor = (betest == 1) ? 1 : 0; - - /* verify against sizes */ - if (state->decompress.video.valid() && (state->decompress.video.width() < width || state->decompress.video.height() < height)) - return AVCERR_VIDEO_TOO_LARGE; - for (chnum = 0; chnum < channels; chnum++) - if (state->decompress.audio[chnum] != NULL && state->decompress.maxsamples < samples) - return AVCERR_AUDIO_TOO_LARGE; - if (state->decompress.metadata != NULL && state->decompress.maxmetalength < metasize) - return AVCERR_METADATA_TOO_LARGE; - - /* set the output values */ - if (state->decompress.actsamples != NULL) - *state->decompress.actsamples = samples; - if (state->decompress.actmetalength != NULL) - *state->decompress.actmetalength = metasize; - } - - /* copy the metadata first */ - if (metasize > 0) - { - if (metastart != NULL) - memcpy(metastart, source + srcoffs, metasize); - srcoffs += metasize; - } - - /* decode the audio channels */ - if (channels > 0) - { - /* decode the audio */ - err = decode_audio(state, channels, samples, source + srcoffs, audiostart, audioxor, &source[8]); - if (err != AVCERR_NONE) - return err; - - /* advance the pointers past the data */ - srcoffs += (source[8] << 8) + source[9]; - for (chnum = 0; chnum < channels; chnum++) - srcoffs += (source[10 + 2 * chnum] << 8) + source[11 + 2 * chnum]; - } - - /* decode the video data */ - if (width > 0 && height > 0 && videostart != NULL) - { - /* decode the video */ - err = decode_video(state, width, height, source + srcoffs, complength - srcoffs, videostart, videostride, videoxor); - if (err != AVCERR_NONE) - return err; - } - return AVCERR_NONE; -} - - - -/*************************************************************************** - ENCODING HELPERS -***************************************************************************/ - -/*------------------------------------------------- - encode_audio - encode raw audio data - to the destination --------------------------------------------------*/ - -static avcomp_error encode_audio(avcomp_state *state, int channels, int samples, const UINT8 **source, int sourcexor, UINT8 *dest, UINT8 *sizes) -{ - UINT32 size, huffsize, totalsize; - huffman_context *contexts[2]; - huffman_error hufferr; - UINT8 *output = dest; - int chnum, sampnum; - UINT8 *deltabuf; - - /* iterate over channels to compute deltas */ - deltabuf = state->audiodata; - for (chnum = 0; chnum < channels; chnum++) - { - const UINT8 *srcdata = source[chnum]; - INT16 prevsample = 0; - - /* extract audio data into hi and lo deltas stored in big-endian order */ - for (sampnum = 0; sampnum < samples; sampnum++) - { - INT16 newsample = (srcdata[0 ^ sourcexor] << 8) | srcdata[1 ^ sourcexor]; - INT16 delta = newsample - prevsample; - prevsample = newsample; - *deltabuf++ = delta >> 8; - *deltabuf++ = delta; - srcdata += 2; - } - } - - /* compute the trees */ - contexts[0] = state->audiohicontext; - contexts[1] = state->audiolocontext; - hufferr = huffman_compute_tree_interleaved(2, contexts, state->audiodata, samples * 2, channels, samples * 2, 0); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - - /* export them to the output */ - hufferr = huffman_export_tree(state->audiohicontext, output, 256, &size); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - output += size; - hufferr = huffman_export_tree(state->audiolocontext, output, 256, &size); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - output += size; - - /* note the size of the two trees */ - huffsize = output - dest; - sizes[0] = huffsize >> 8; - sizes[1] = huffsize; - - /* iterate over channels */ - totalsize = huffsize; - for (chnum = 0; chnum < channels; chnum++) - { - const UINT8 *input = state->audiodata + chnum * samples * 2; - - /* encode the data */ - hufferr = huffman_encode_data_interleaved(2, contexts, input, samples * 2, 1, 0, 0, output, samples * 2, &size); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - output += size; - - /* store the size of this stream */ - totalsize += size; - if (totalsize >= channels * samples * 2) - break; - sizes[chnum * 2 + 2] = size >> 8; - sizes[chnum * 2 + 3] = size; - } - - /* if we ran out of room, throw it all away and just store raw */ - if (chnum < channels) - { - memcpy(dest, state->audiodata, channels * samples * 2); - size = samples * 2; - sizes[0] = sizes[1] = 0; - for (chnum = 0; chnum < channels; chnum++) - { - sizes[chnum * 2 + 2] = size >> 8; - sizes[chnum * 2 + 3] = size; - } - } - - return AVCERR_NONE; -} - - -/*------------------------------------------------- - encode_video - encode raw video data - to the destination --------------------------------------------------*/ - -static avcomp_error encode_video(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 sstride, UINT32 sxor, UINT8 *dest, UINT32 *complength) -{ - /* only lossless supported at this time */ - return encode_video_lossless(state, width, height, source, sstride, sxor, dest, complength); -} - - -/*------------------------------------------------- - encode_video_lossless - do a lossless video - encoding using deltas and huffman encoding --------------------------------------------------*/ - -static avcomp_error encode_video_lossless(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 sstride, UINT32 sxor, UINT8 *dest, UINT32 *complength) -{ - UINT32 srcbytes = width * height * 2; - huffman_context *contexts[4]; - huffman_error hufferr; - UINT32 outbytes; - UINT8 *output; - - /* set up the output; first byte is 0x80 to indicate lossless encoding */ - output = dest; - *output++ = 0x80; - - /* now encode to the destination using two trees, one for the Y and one for the Cr/Cb */ - contexts[0] = state->ycontext; - contexts[1] = state->cbcontext; - contexts[2] = state->ycontext; - contexts[3] = state->crcontext; - - /* compute the histograms for the data */ - hufferr = huffman_deltarle_compute_tree_interleaved(4, contexts, source, width * 2, height, sstride, sxor); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - - /* export the trees to the data stream */ - hufferr = huffman_deltarle_export_tree(state->ycontext, output, 256, &outbytes); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - output += outbytes; - hufferr = huffman_deltarle_export_tree(state->cbcontext, output, 256, &outbytes); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - output += outbytes; - hufferr = huffman_deltarle_export_tree(state->crcontext, output, 256, &outbytes); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - output += outbytes; - - /* encode the data using the trees */ - hufferr = huffman_deltarle_encode_data_interleaved(4, contexts, source, width * 2, height, sstride, sxor, output, srcbytes, &outbytes); - if (hufferr != HUFFERR_NONE) - return AVCERR_COMPRESSION_ERROR; - output += outbytes; - - /* set the final length */ - *complength = output - dest; - return AVCERR_NONE; -} - - - -/*************************************************************************** - DECODING HELPERS -***************************************************************************/ - -/*------------------------------------------------- - decode_audio - decode audio from a - compressed data stream --------------------------------------------------*/ - -static avcomp_error decode_audio(avcomp_state *state, int channels, int samples, const UINT8 *source, UINT8 **dest, UINT32 dxor, const UINT8 *sizes) -{ - huffman_context *contexts[2]; - UINT32 actsize, huffsize; - huffman_error hufferr; - int chnum, sampnum; - UINT16 size; - - /* if no huffman length, just copy the data */ - size = (sizes[0] << 8) | sizes[1]; - if (size == 0) - { - /* loop over channels */ - for (chnum = 0; chnum < channels; chnum++) - { - UINT8 *curdest = dest[chnum]; - - /* extract the size of this channel */ - size = (sizes[chnum * 2 + 2] << 8) | sizes[chnum * 2 + 3]; - - /* extract data from the deltas */ - if (dest[chnum] != NULL) - { - INT16 prevsample = 0; - for (sampnum = 0; sampnum < samples; sampnum++) - { - INT16 delta = (source[0] << 8) | source[1]; - INT16 newsample = prevsample + delta; - prevsample = newsample; - - curdest[0 ^ dxor] = newsample >> 8; - curdest[1 ^ dxor] = newsample; - source += 2; - curdest += 2; - } - } - else - source += size; - } - return AVCERR_NONE; - } - - /* extract the huffman trees */ - hufferr = huffman_import_tree(state->audiohicontext, source, size, &actsize); - if (hufferr != HUFFERR_NONE) - return AVCERR_INVALID_DATA; - source += actsize; - huffsize = actsize; - - hufferr = huffman_import_tree(state->audiolocontext, source, size, &actsize); - if (hufferr != HUFFERR_NONE) - return AVCERR_INVALID_DATA; - source += actsize; - huffsize += actsize; - if (huffsize != size) - return AVCERR_INVALID_DATA; - - /* set up the contexts */ - contexts[0] = state->audiohicontext; - contexts[1] = state->audiolocontext; - - /* now loop over channels and decode their data */ - for (chnum = 0; chnum < channels; chnum++) - { - /* extract the size of this channel */ - size = (sizes[chnum * 2 + 2] << 8) | sizes[chnum * 2 + 3]; - - /* decode the data */ - if (dest[chnum] != NULL) - { - UINT8 *deltabuf = state->audiodata + chnum * samples * 2; - hufferr = huffman_decode_data_interleaved(2, contexts, source, size, deltabuf, samples * 2, 1, 0, 0, &actsize); - if (hufferr != HUFFERR_NONE || actsize != size) - return AVCERR_INVALID_DATA; - } - - /* advance */ - source += size; - } - - /* reassemble audio from the deltas */ - for (chnum = 0; chnum < channels; chnum++) - if (dest[chnum] != NULL) - { - UINT8 *deltabuf = state->audiodata + chnum * samples * 2; - UINT8 *curdest = dest[chnum]; - INT16 prevsample = 0; - - for (sampnum = 0; sampnum < samples; sampnum++) - { - INT16 delta = (deltabuf[0] << 8) | deltabuf[1]; - INT16 newsample = prevsample + delta; - prevsample = newsample; - - curdest[0 ^ dxor] = newsample >> 8; - curdest[1 ^ dxor] = newsample; - deltabuf += 2; - curdest += 2; - } - } - - return AVCERR_NONE; -} - - -/*------------------------------------------------- - decode_video - decode video from a - compressed data stream --------------------------------------------------*/ - -static avcomp_error decode_video(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 complength, UINT8 *dest, UINT32 dstride, UINT32 dxor) -{ - /* if the high bit of the first byte is set, we decode losslessly */ - if (source[0] & 0x80) - return decode_video_lossless(state, width, height, source, complength, dest, dstride, dxor); - else - return AVCERR_INVALID_DATA; -} - - -/*------------------------------------------------- - decode_video_lossless - do a lossless video - decoding using deltas and huffman encoding --------------------------------------------------*/ - -static avcomp_error decode_video_lossless(avcomp_state *state, int width, int height, const UINT8 *source, UINT32 complength, UINT8 *dest, UINT32 deststride, UINT32 destxor) -{ - const UINT8 *sourceend = source + complength; - huffman_context *contexts[4]; - huffman_error hufferr; - UINT32 actsize; - - /* skip the first byte */ - source++; - - /* import the tables */ - hufferr = huffman_deltarle_import_tree(state->ycontext, source, sourceend - source, &actsize); - if (hufferr != HUFFERR_NONE) - return AVCERR_INVALID_DATA; - source += actsize; - hufferr = huffman_deltarle_import_tree(state->cbcontext, source, sourceend - source, &actsize); - if (hufferr != HUFFERR_NONE) - return AVCERR_INVALID_DATA; - source += actsize; - hufferr = huffman_deltarle_import_tree(state->crcontext, source, sourceend - source, &actsize); - if (hufferr != HUFFERR_NONE) - return AVCERR_INVALID_DATA; - source += actsize; - - /* set up the decoding contexts */ - contexts[0] = state->ycontext; - contexts[1] = state->cbcontext; - contexts[2] = state->ycontext; - contexts[3] = state->crcontext; - - /* decode to the destination */ - hufferr = huffman_deltarle_decode_data_interleaved(4, contexts, source, sourceend - source, dest, width * 2, height, deststride, destxor, &actsize); - if (hufferr != HUFFERR_NONE) - return AVCERR_INVALID_DATA; - if (actsize != sourceend - source) - return AVCERR_INVALID_DATA; - - return AVCERR_NONE; -} |