/*1* Copyright (c) 1999-2000 Image Power, Inc. and the University of2* British Columbia.3* Copyright (c) 2001-2003 Michael David Adams.4* All rights reserved.5*/67/* __START_OF_JASPER_LICENSE__8*9* JasPer License Version 2.010*11* Copyright (c) 2001-2006 Michael David Adams12* Copyright (c) 1999-2000 Image Power, Inc.13* Copyright (c) 1999-2000 The University of British Columbia14*15* All rights reserved.16*17* Permission is hereby granted, free of charge, to any person (the18* "User") obtaining a copy of this software and associated documentation19* files (the "Software"), to deal in the Software without restriction,20* including without limitation the rights to use, copy, modify, merge,21* publish, distribute, and/or sell copies of the Software, and to permit22* persons to whom the Software is furnished to do so, subject to the23* following conditions:24*25* 1. The above copyright notices and this permission notice (which26* includes the disclaimer below) shall be included in all copies or27* substantial portions of the Software.28*29* 2. The name of a copyright holder shall not be used to endorse or30* promote products derived from the Software without specific prior31* written permission.32*33* THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS34* LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER35* THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS36* "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING37* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A38* PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO39* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL40* INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING41* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,42* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION43* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE44* PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE45* THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.46* EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS47* BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL48* PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS49* GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE50* ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE51* IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL52* SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,53* AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL54* SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH55* THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,56* PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH57* RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY58* EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.59*60* __END_OF_JASPER_LICENSE__61*/6263/*64* MQ Arithmetic Decoder65*66* $Id: jpc_mqdec.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $67*/6869/******************************************************************************\70* Includes.71\******************************************************************************/7273#include <assert.h>74#include <stdlib.h>75#include <stdarg.h>7677#include "jasper/jas_types.h"78#include "jasper/jas_malloc.h"79#include "jasper/jas_math.h"80#include "jasper/jas_debug.h"8182#include "jpc_mqdec.h"8384/******************************************************************************\85* Local macros.86\******************************************************************************/8788#if defined(DEBUG)89#define MQDEC_CALL(n, x) \90((jas_getdbglevel() >= (n)) ? ((void)(x)) : ((void)0))91#else92#define MQDEC_CALL(n, x)93#endif9495/******************************************************************************\96* Local function prototypes.97\******************************************************************************/9899static void jpc_mqdec_bytein(jpc_mqdec_t *mqdec);100101/******************************************************************************\102* Code for creation and destruction of a MQ decoder.103\******************************************************************************/104105/* Create a MQ decoder. */106jpc_mqdec_t *jpc_mqdec_create(int maxctxs, jas_stream_t *in)107{108jpc_mqdec_t *mqdec;109110/* There must be at least one context. */111assert(maxctxs > 0);112113/* Allocate memory for the MQ decoder. */114if (!(mqdec = jas_malloc(sizeof(jpc_mqdec_t)))) {115goto error;116}117mqdec->in = in;118mqdec->maxctxs = maxctxs;119/* Allocate memory for the per-context state information. */120if (!(mqdec->ctxs = jas_alloc2(mqdec->maxctxs, sizeof(jpc_mqstate_t *)))) {121goto error;122}123/* Set the current context to the first context. */124mqdec->curctx = mqdec->ctxs;125126/* If an input stream has been associated with the MQ decoder,127initialize the decoder state from the stream. */128if (mqdec->in) {129jpc_mqdec_init(mqdec);130}131/* Initialize the per-context state information. */132jpc_mqdec_setctxs(mqdec, 0, 0);133134return mqdec;135136error:137/* Oops... Something has gone wrong. */138if (mqdec) {139jpc_mqdec_destroy(mqdec);140}141return 0;142}143144/* Destroy a MQ decoder. */145void jpc_mqdec_destroy(jpc_mqdec_t *mqdec)146{147if (mqdec->ctxs) {148jas_free(mqdec->ctxs);149}150jas_free(mqdec);151}152153/******************************************************************************\154* Code for initialization of a MQ decoder.155\******************************************************************************/156157/* Initialize the state of a MQ decoder. */158159void jpc_mqdec_init(jpc_mqdec_t *mqdec)160{161int c;162163mqdec->eof = 0;164mqdec->creg = 0;165/* Get the next byte from the input stream. */166if ((c = jas_stream_getc(mqdec->in)) == EOF) {167/* We have encountered an I/O error or EOF. */168c = 0xff;169mqdec->eof = 1;170}171mqdec->inbuffer = c;172mqdec->creg += mqdec->inbuffer << 16;173jpc_mqdec_bytein(mqdec);174mqdec->creg <<= 7;175mqdec->ctreg -= 7;176mqdec->areg = 0x8000;177}178179/* Set the input stream for a MQ decoder. */180181void jpc_mqdec_setinput(jpc_mqdec_t *mqdec, jas_stream_t *in)182{183mqdec->in = in;184}185186/* Initialize one or more contexts. */187188void jpc_mqdec_setctxs(jpc_mqdec_t *mqdec, int numctxs, jpc_mqctx_t *ctxs)189{190jpc_mqstate_t **ctx;191int n;192193ctx = mqdec->ctxs;194n = JAS_MIN(mqdec->maxctxs, numctxs);195while (--n >= 0) {196*ctx = &jpc_mqstates[2 * ctxs->ind + ctxs->mps];197++ctx;198++ctxs;199}200n = mqdec->maxctxs - numctxs;201while (--n >= 0) {202*ctx = &jpc_mqstates[0];203++ctx;204}205}206207/* Initialize a context. */208209void jpc_mqdec_setctx(jpc_mqdec_t *mqdec, int ctxno, jpc_mqctx_t *ctx)210{211jpc_mqstate_t **ctxi;212ctxi = &mqdec->ctxs[ctxno];213*ctxi = &jpc_mqstates[2 * ctx->ind + ctx->mps];214}215216/******************************************************************************\217* Code for decoding a bit.218\******************************************************************************/219220/* Decode a bit. */221222int jpc_mqdec_getbit_func(register jpc_mqdec_t *mqdec)223{224int bit;225JAS_DBGLOG(100, ("jpc_mqdec_getbit_func(%p)\n", mqdec));226MQDEC_CALL(100, jpc_mqdec_dump(mqdec, stderr));227bit = jpc_mqdec_getbit_macro(mqdec);228MQDEC_CALL(100, jpc_mqdec_dump(mqdec, stderr));229JAS_DBGLOG(100, ("ctx = %d, decoded %d\n", mqdec->curctx -230mqdec->ctxs, bit));231return bit;232}233234/* Apply MPS_EXCHANGE algorithm (with RENORMD). */235int jpc_mqdec_mpsexchrenormd(register jpc_mqdec_t *mqdec)236{237int ret;238register jpc_mqstate_t *state = *mqdec->curctx;239jpc_mqdec_mpsexchange(mqdec->areg, state->qeval, mqdec->curctx, ret);240jpc_mqdec_renormd(mqdec->areg, mqdec->creg, mqdec->ctreg, mqdec->in,241mqdec->eof, mqdec->inbuffer);242return ret;243}244245/* Apply LPS_EXCHANGE algorithm (with RENORMD). */246int jpc_mqdec_lpsexchrenormd(register jpc_mqdec_t *mqdec)247{248int ret;249register jpc_mqstate_t *state = *mqdec->curctx;250jpc_mqdec_lpsexchange(mqdec->areg, state->qeval, mqdec->curctx, ret);251jpc_mqdec_renormd(mqdec->areg, mqdec->creg, mqdec->ctreg, mqdec->in,252mqdec->eof, mqdec->inbuffer);253return ret;254}255256/******************************************************************************\257* Support code.258\******************************************************************************/259260/* Apply the BYTEIN algorithm. */261static void jpc_mqdec_bytein(jpc_mqdec_t *mqdec)262{263int c;264unsigned char prevbuf;265266if (!mqdec->eof) {267if ((c = jas_stream_getc(mqdec->in)) == EOF) {268mqdec->eof = 1;269c = 0xff;270}271prevbuf = mqdec->inbuffer;272mqdec->inbuffer = c;273if (prevbuf == 0xff) {274if (c > 0x8f) {275mqdec->creg += 0xff00;276mqdec->ctreg = 8;277} else {278mqdec->creg += c << 9;279mqdec->ctreg = 7;280}281} else {282mqdec->creg += c << 8;283mqdec->ctreg = 8;284}285} else {286mqdec->creg += 0xff00;287mqdec->ctreg = 8;288}289}290291/******************************************************************************\292* Code for debugging.293\******************************************************************************/294295/* Dump a MQ decoder to a stream for debugging. */296297void jpc_mqdec_dump(jpc_mqdec_t *mqdec, FILE *out)298{299fprintf(out, "MQDEC A = %08lx, C = %08lx, CT=%08lx, ",300(unsigned long) mqdec->areg, (unsigned long) mqdec->creg,301(unsigned long) mqdec->ctreg);302fprintf(out, "CTX = %d, ", (int)(mqdec->curctx - mqdec->ctxs));303fprintf(out, "IND %d, MPS %d, QEVAL %x\n", (int)(*mqdec->curctx -304jpc_mqstates), (int)(*mqdec->curctx)->mps, (int)(*mqdec->curctx)->qeval);305}306307308