1/* 2 * Copyright (c) 1999-2000 Image Power, Inc. and the University of 3 * British Columbia. 4 * Copyright (c) 2001-2003 Michael David Adams. 5 * All rights reserved. 6 */ 7 8/* __START_OF_JASPER_LICENSE__ 9 * 10 * JasPer License Version 2.0 11 * 12 * Copyright (c) 2001-2006 Michael David Adams 13 * Copyright (c) 1999-2000 Image Power, Inc. 14 * Copyright (c) 1999-2000 The University of British Columbia 15 * 16 * All rights reserved. 17 * 18 * Permission is hereby granted, free of charge, to any person (the 19 * "User") obtaining a copy of this software and associated documentation 20 * files (the "Software"), to deal in the Software without restriction, 21 * including without limitation the rights to use, copy, modify, merge, 22 * publish, distribute, and/or sell copies of the Software, and to permit 23 * persons to whom the Software is furnished to do so, subject to the 24 * following conditions: 25 * 26 * 1. The above copyright notices and this permission notice (which 27 * includes the disclaimer below) shall be included in all copies or 28 * substantial portions of the Software. 29 * 30 * 2. The name of a copyright holder shall not be used to endorse or 31 * promote products derived from the Software without specific prior 32 * written permission. 33 * 34 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS 35 * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER 36 * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 37 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 38 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 39 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO 40 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 41 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 42 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 43 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 44 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE 45 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE 46 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. 47 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS 48 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL 49 * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS 50 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE 51 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE 52 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL 53 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, 54 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL 55 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH 56 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, 57 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH 58 * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY 59 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. 60 * 61 * __END_OF_JASPER_LICENSE__ 62 */ 63 64/* 65 * MQ Arithmetic Decoder 66 * 67 * $Id: jpc_mqdec.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $ 68 */ 69 70/******************************************************************************\ 71* Includes. 72\******************************************************************************/ 73 74#include <assert.h> 75#include <stdlib.h> 76#include <stdarg.h> 77 78#include "jasper/jas_types.h" 79#include "jasper/jas_malloc.h" 80#include "jasper/jas_math.h" 81#include "jasper/jas_debug.h" 82 83#include "jpc_mqdec.h" 84 85/******************************************************************************\ 86* Local macros. 87\******************************************************************************/ 88 89#if defined(DEBUG) 90#define MQDEC_CALL(n, x) \ 91 ((jas_getdbglevel() >= (n)) ? ((void)(x)) : ((void)0)) 92#else 93#define MQDEC_CALL(n, x) 94#endif 95 96/******************************************************************************\ 97* Local function prototypes. 98\******************************************************************************/ 99 100static void jpc_mqdec_bytein(jpc_mqdec_t *mqdec); 101 102/******************************************************************************\ 103* Code for creation and destruction of a MQ decoder. 104\******************************************************************************/ 105 106/* Create a MQ decoder. */ 107jpc_mqdec_t *jpc_mqdec_create(int maxctxs, jas_stream_t *in) 108{ 109 jpc_mqdec_t *mqdec; 110 111 /* There must be at least one context. */ 112 assert(maxctxs > 0); 113 114 /* Allocate memory for the MQ decoder. */ 115 if (!(mqdec = jas_malloc(sizeof(jpc_mqdec_t)))) { 116 goto error; 117 } 118 mqdec->in = in; 119 mqdec->maxctxs = maxctxs; 120 /* Allocate memory for the per-context state information. */ 121 if (!(mqdec->ctxs = jas_alloc2(mqdec->maxctxs, sizeof(jpc_mqstate_t *)))) { 122 goto error; 123 } 124 /* Set the current context to the first context. */ 125 mqdec->curctx = mqdec->ctxs; 126 127 /* If an input stream has been associated with the MQ decoder, 128 initialize the decoder state from the stream. */ 129 if (mqdec->in) { 130 jpc_mqdec_init(mqdec); 131 } 132 /* Initialize the per-context state information. */ 133 jpc_mqdec_setctxs(mqdec, 0, 0); 134 135 return mqdec; 136 137error: 138 /* Oops... Something has gone wrong. */ 139 if (mqdec) { 140 jpc_mqdec_destroy(mqdec); 141 } 142 return 0; 143} 144 145/* Destroy a MQ decoder. */ 146void jpc_mqdec_destroy(jpc_mqdec_t *mqdec) 147{ 148 if (mqdec->ctxs) { 149 jas_free(mqdec->ctxs); 150 } 151 jas_free(mqdec); 152} 153 154/******************************************************************************\ 155* Code for initialization of a MQ decoder. 156\******************************************************************************/ 157 158/* Initialize the state of a MQ decoder. */ 159 160void jpc_mqdec_init(jpc_mqdec_t *mqdec) 161{ 162 int c; 163 164 mqdec->eof = 0; 165 mqdec->creg = 0; 166 /* Get the next byte from the input stream. */ 167 if ((c = jas_stream_getc(mqdec->in)) == EOF) { 168 /* We have encountered an I/O error or EOF. */ 169 c = 0xff; 170 mqdec->eof = 1; 171 } 172 mqdec->inbuffer = c; 173 mqdec->creg += mqdec->inbuffer << 16; 174 jpc_mqdec_bytein(mqdec); 175 mqdec->creg <<= 7; 176 mqdec->ctreg -= 7; 177 mqdec->areg = 0x8000; 178} 179 180/* Set the input stream for a MQ decoder. */ 181 182void jpc_mqdec_setinput(jpc_mqdec_t *mqdec, jas_stream_t *in) 183{ 184 mqdec->in = in; 185} 186 187/* Initialize one or more contexts. */ 188 189void jpc_mqdec_setctxs(jpc_mqdec_t *mqdec, int numctxs, jpc_mqctx_t *ctxs) 190{ 191 jpc_mqstate_t **ctx; 192 int n; 193 194 ctx = mqdec->ctxs; 195 n = JAS_MIN(mqdec->maxctxs, numctxs); 196 while (--n >= 0) { 197 *ctx = &jpc_mqstates[2 * ctxs->ind + ctxs->mps]; 198 ++ctx; 199 ++ctxs; 200 } 201 n = mqdec->maxctxs - numctxs; 202 while (--n >= 0) { 203 *ctx = &jpc_mqstates[0]; 204 ++ctx; 205 } 206} 207 208/* Initialize a context. */ 209 210void jpc_mqdec_setctx(jpc_mqdec_t *mqdec, int ctxno, jpc_mqctx_t *ctx) 211{ 212 jpc_mqstate_t **ctxi; 213 ctxi = &mqdec->ctxs[ctxno]; 214 *ctxi = &jpc_mqstates[2 * ctx->ind + ctx->mps]; 215} 216 217/******************************************************************************\ 218* Code for decoding a bit. 219\******************************************************************************/ 220 221/* Decode a bit. */ 222 223int jpc_mqdec_getbit_func(register jpc_mqdec_t *mqdec) 224{ 225 int bit; 226 JAS_DBGLOG(100, ("jpc_mqdec_getbit_func(%p)\n", mqdec)); 227 MQDEC_CALL(100, jpc_mqdec_dump(mqdec, stderr)); 228 bit = jpc_mqdec_getbit_macro(mqdec); 229 MQDEC_CALL(100, jpc_mqdec_dump(mqdec, stderr)); 230 JAS_DBGLOG(100, ("ctx = %d, decoded %d\n", mqdec->curctx - 231 mqdec->ctxs, bit)); 232 return bit; 233} 234 235/* Apply MPS_EXCHANGE algorithm (with RENORMD). */ 236int jpc_mqdec_mpsexchrenormd(register jpc_mqdec_t *mqdec) 237{ 238 int ret; 239 register jpc_mqstate_t *state = *mqdec->curctx; 240 jpc_mqdec_mpsexchange(mqdec->areg, state->qeval, mqdec->curctx, ret); 241 jpc_mqdec_renormd(mqdec->areg, mqdec->creg, mqdec->ctreg, mqdec->in, 242 mqdec->eof, mqdec->inbuffer); 243 return ret; 244} 245 246/* Apply LPS_EXCHANGE algorithm (with RENORMD). */ 247int jpc_mqdec_lpsexchrenormd(register jpc_mqdec_t *mqdec) 248{ 249 int ret; 250 register jpc_mqstate_t *state = *mqdec->curctx; 251 jpc_mqdec_lpsexchange(mqdec->areg, state->qeval, mqdec->curctx, ret); 252 jpc_mqdec_renormd(mqdec->areg, mqdec->creg, mqdec->ctreg, mqdec->in, 253 mqdec->eof, mqdec->inbuffer); 254 return ret; 255} 256 257/******************************************************************************\ 258* Support code. 259\******************************************************************************/ 260 261/* Apply the BYTEIN algorithm. */ 262static void jpc_mqdec_bytein(jpc_mqdec_t *mqdec) 263{ 264 int c; 265 unsigned char prevbuf; 266 267 if (!mqdec->eof) { 268 if ((c = jas_stream_getc(mqdec->in)) == EOF) { 269 mqdec->eof = 1; 270 c = 0xff; 271 } 272 prevbuf = mqdec->inbuffer; 273 mqdec->inbuffer = c; 274 if (prevbuf == 0xff) { 275 if (c > 0x8f) { 276 mqdec->creg += 0xff00; 277 mqdec->ctreg = 8; 278 } else { 279 mqdec->creg += c << 9; 280 mqdec->ctreg = 7; 281 } 282 } else { 283 mqdec->creg += c << 8; 284 mqdec->ctreg = 8; 285 } 286 } else { 287 mqdec->creg += 0xff00; 288 mqdec->ctreg = 8; 289 } 290} 291 292/******************************************************************************\ 293* Code for debugging. 294\******************************************************************************/ 295 296/* Dump a MQ decoder to a stream for debugging. */ 297 298void jpc_mqdec_dump(jpc_mqdec_t *mqdec, FILE *out) 299{ 300 fprintf(out, "MQDEC A = %08lx, C = %08lx, CT=%08lx, ", 301 (unsigned long) mqdec->areg, (unsigned long) mqdec->creg, 302 (unsigned long) mqdec->ctreg); 303 fprintf(out, "CTX = %d, ", (int)(mqdec->curctx - mqdec->ctxs)); 304 fprintf(out, "IND %d, MPS %d, QEVAL %x\n", (int)(*mqdec->curctx - 305 jpc_mqstates), (int)(*mqdec->curctx)->mps, (int)(*mqdec->curctx)->qeval); 306} 307