jpc_mqdec.c (9552B)
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) 1999-2000 Image Power, Inc. 13 * Copyright (c) 1999-2000 The University of British Columbia 14 * Copyright (c) 2001-2003 Michael David Adams 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 1918 2005-07-24 14:12:08Z baford $ 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 100 static 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. */ 107 jpc_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_malloc(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 137 error: 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. */ 146 void 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 160 void 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 182 void 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 189 void 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 210 void 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 223 int 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). */ 236 int 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). */ 247 int 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. */ 262 static 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 298 void 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 }